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

Code
Comments
Other
Rev Date Author Line
2023 19 Sep 13 olle 1 package net.sf.basedb.reggie.servlet;
2023 19 Sep 13 olle 2
2023 19 Sep 13 olle 3 import java.io.IOException;
2023 19 Sep 13 olle 4 import java.util.ArrayList;
2023 19 Sep 13 olle 5 import java.util.Collections;
2023 19 Sep 13 olle 6 import java.util.Date;
2023 19 Sep 13 olle 7 import java.util.List;
2023 19 Sep 13 olle 8 import java.util.TreeMap;
2023 19 Sep 13 olle 9
2023 19 Sep 13 olle 10 import javax.servlet.ServletException;
2023 19 Sep 13 olle 11 import javax.servlet.http.HttpServlet;
2023 19 Sep 13 olle 12 import javax.servlet.http.HttpServletRequest;
2023 19 Sep 13 olle 13 import javax.servlet.http.HttpServletResponse;
2023 19 Sep 13 olle 14
7024 07 Feb 23 nicklas 15 import org.apache.commons.lang3.time.FastDateFormat;
2023 19 Sep 13 olle 16 import org.json.simple.JSONArray;
2023 19 Sep 13 olle 17 import org.json.simple.JSONObject;
2023 19 Sep 13 olle 18
2023 19 Sep 13 olle 19 import net.sf.basedb.core.BioMaterialEvent;
2023 19 Sep 13 olle 20 import net.sf.basedb.core.BioSource;
2023 19 Sep 13 olle 21 import net.sf.basedb.core.DbControl;
2023 19 Sep 13 olle 22 import net.sf.basedb.core.ItemQuery;
5919 24 Apr 20 nicklas 23 import net.sf.basedb.core.ProgressReporter;
2023 19 Sep 13 olle 24 import net.sf.basedb.core.Sample;
2023 19 Sep 13 olle 25 import net.sf.basedb.core.SessionControl;
2023 19 Sep 13 olle 26 import net.sf.basedb.core.query.Hql;
2023 19 Sep 13 olle 27 import net.sf.basedb.core.query.Orders;
2023 19 Sep 13 olle 28 import net.sf.basedb.core.query.Restrictions;
2023 19 Sep 13 olle 29 import net.sf.basedb.core.snapshot.SnapshotManager;
5919 24 Apr 20 nicklas 30 import net.sf.basedb.reggie.AbortableProgressReporter;
2598 22 Aug 14 nicklas 31 import net.sf.basedb.reggie.JsonUtil;
2023 19 Sep 13 olle 32 import net.sf.basedb.reggie.Reggie;
5387 26 Apr 19 nicklas 33 import net.sf.basedb.reggie.activity.ActivityDef;
2023 19 Sep 13 olle 34 import net.sf.basedb.reggie.converter.DateToStringConverter;
3059 19 Dec 14 nicklas 35 import net.sf.basedb.reggie.counter.CounterService;
2023 19 Sep 13 olle 36 import net.sf.basedb.reggie.dao.Annotationtype;
2023 19 Sep 13 olle 37 import net.sf.basedb.reggie.dao.Blood;
2023 19 Sep 13 olle 38 import net.sf.basedb.reggie.dao.Case;
2023 19 Sep 13 olle 39 import net.sf.basedb.reggie.dao.Consent;
2023 19 Sep 13 olle 40 import net.sf.basedb.reggie.dao.Patient;
4900 10 Jul 18 nicklas 41 import net.sf.basedb.reggie.dao.ReggieItem;
2161 09 Dec 13 nicklas 42 import net.sf.basedb.reggie.dao.ReggieRole;
2023 19 Sep 13 olle 43 import net.sf.basedb.reggie.dao.Subtype;
5910 17 Apr 20 nicklas 44 import net.sf.basedb.reggie.plugins.FollowupBloodImporter;
2023 19 Sep 13 olle 45 import net.sf.basedb.util.Values;
2023 19 Sep 13 olle 46 import net.sf.basedb.util.error.ThrowableUtil;
2023 19 Sep 13 olle 47
2023 19 Sep 13 olle 48
2023 19 Sep 13 olle 49 public class BloodFollowUpRegistrationServlet 
2023 19 Sep 13 olle 50   extends HttpServlet 
2023 19 Sep 13 olle 51 {
2023 19 Sep 13 olle 52   private final static String BLOOD_FILTER_FOLLOW_UP_06 = "FollowUp06";
2023 19 Sep 13 olle 53   private final static String BLOOD_FILTER_FOLLOW_UP_12 = "FollowUp12";
2023 19 Sep 13 olle 54   private final static String BLOOD_FILTER_FOLLOW_UP_36 = "FollowUp36";
2023 19 Sep 13 olle 55
2023 19 Sep 13 olle 56   private static final long serialVersionUID = 8770173686061080429L;
2023 19 Sep 13 olle 57
2023 19 Sep 13 olle 58   public BloodFollowUpRegistrationServlet()
2023 19 Sep 13 olle 59   {}
2023 19 Sep 13 olle 60
2023 19 Sep 13 olle 61   @Override
2023 19 Sep 13 olle 62   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
2023 19 Sep 13 olle 63     throws ServletException, IOException 
2023 19 Sep 13 olle 64   {
2023 19 Sep 13 olle 65     String cmd = req.getParameter("cmd");
2598 22 Aug 14 nicklas 66     JsonUtil.setJsonResponseHeaders(resp);
2023 19 Sep 13 olle 67     
2023 19 Sep 13 olle 68     JSONObject json = new JSONObject();
2023 19 Sep 13 olle 69     json.put("status", "ok");
2023 19 Sep 13 olle 70   
3975 26 May 16 nicklas 71     final SessionControl sc = Reggie.getSessionControl(req);
2023 19 Sep 13 olle 72     DbControl dc = null;
2023 19 Sep 13 olle 73     try
2023 19 Sep 13 olle 74     {
2023 19 Sep 13 olle 75       if ("GetBloodFollowUpInfo".equals(cmd))
2023 19 Sep 13 olle 76       {
2023 19 Sep 13 olle 77         /*
2023 19 Sep 13 olle 78           Load information about a single follow-up blood item when given the RCCID number/barcode
2023 19 Sep 13 olle 79           If an item is found we will load annotations, and information about the patient 
2023 19 Sep 13 olle 80           it is associated with.
2023 19 Sep 13 olle 81         */
6329 14 Jun 21 nicklas 82         dc = sc.newDbControl(":Follow-up blood referral form registration");
2023 19 Sep 13 olle 83         
2023 19 Sep 13 olle 84         // Find blood by RCCID number
2023 19 Sep 13 olle 85         String rccidNumber = req.getParameter("rccidNumber");
2023 19 Sep 13 olle 86         Blood blood = Blood.findByRccidNumber(dc, rccidNumber);
2023 19 Sep 13 olle 87         Patient patient = null;
2023 19 Sep 13 olle 88         String bloodName = null;
2023 19 Sep 13 olle 89         String caseName = null;
2023 19 Sep 13 olle 90
2023 19 Sep 13 olle 91         if (blood != null)
2023 19 Sep 13 olle 92         {
2023 19 Sep 13 olle 93           // Check that the registration is not prohibited
2023 19 Sep 13 olle 94           blood.verifyConsent(dc, null);
2023 19 Sep 13 olle 95           
2023 19 Sep 13 olle 96           // ... blood annotations
2023 19 Sep 13 olle 97           blood.loadAnnotations(dc, "samplingDate", Annotationtype.BLOOD_SAMPLING_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
2023 19 Sep 13 olle 98           blood.loadAnnotations(dc, "freezerDate", Annotationtype.BLOOD_FREEZER_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
2023 19 Sep 13 olle 99           blood.loadAnnotations(dc, "serum", Annotationtype.BLOOD_SERUM, null);
2023 19 Sep 13 olle 100           blood.loadAnnotations(dc, "bloodSample", Annotationtype.BLOOD_SAMPLE, null);
2023 19 Sep 13 olle 101           blood.loadAnnotations(dc, "otherPathNote", Annotationtype.OTHER_PATH_NOTE, null);
2023 19 Sep 13 olle 102
2023 19 Sep 13 olle 103           // Load the patient associated with the blood item
2023 19 Sep 13 olle 104           patient = Patient.findByBlood(dc, blood);
2023 19 Sep 13 olle 105           
2023 19 Sep 13 olle 106           // Find case name from blood name (blood name = case name + '.b' suffix)
2023 19 Sep 13 olle 107           bloodName = blood.getName();
2023 19 Sep 13 olle 108           int bloodSuffixIndex = bloodName.indexOf(".b");
2023 19 Sep 13 olle 109           if (bloodSuffixIndex >= 0)
2023 19 Sep 13 olle 110           {
2023 19 Sep 13 olle 111             caseName = bloodName.substring(0, bloodSuffixIndex);
2023 19 Sep 13 olle 112           }
2023 19 Sep 13 olle 113         }
2023 19 Sep 13 olle 114         else
2023 19 Sep 13 olle 115         {
2023 19 Sep 13 olle 116           // Could not find the specified follow-up blood item
2023 19 Sep 13 olle 117           // -- Search for other follow-up blood items with the same base RCCID number,
2023 19 Sep 13 olle 118           // i.e. ignoring RCCID suffix letter.
2023 19 Sep 13 olle 119           //
2023 19 Sep 13 olle 120           // Note that we only want to use that follow-up blood item to find
2023 19 Sep 13 olle 121           // the case and patient, but other data is not loaded, since we
2023 19 Sep 13 olle 122           // want to register a new follow-up blood item with another RCCID suffix letter.
2023 19 Sep 13 olle 123           //
2023 19 Sep 13 olle 124           Blood otherBlood = null;
2023 19 Sep 13 olle 125           List<Blood> bloodList = Blood.findAllByBaseRccidNumber(dc, rccidNumber);
2023 19 Sep 13 olle 126           // If follow-up blood items are found, use the first one to find
2023 19 Sep 13 olle 127           // the case and patient
2023 19 Sep 13 olle 128           if (bloodList != null && bloodList.size() > 0)
2023 19 Sep 13 olle 129           {
5415 09 May 19 nicklas 130             otherBlood = bloodList.get(0);
2023 19 Sep 13 olle 131           }
2023 19 Sep 13 olle 132
2023 19 Sep 13 olle 133           if (otherBlood != null)
2023 19 Sep 13 olle 134           {
2023 19 Sep 13 olle 135             // Load the patient associated with the blood item
2023 19 Sep 13 olle 136             patient = Patient.findByBlood(dc, otherBlood);
2023 19 Sep 13 olle 137             
2023 19 Sep 13 olle 138             // Find case name from blood name (blood name = case name + '.b' suffix)
2023 19 Sep 13 olle 139             String otherBloodName = otherBlood.getName();
2023 19 Sep 13 olle 140             int otherBloodSuffixIndex = otherBloodName.indexOf(".b");
2023 19 Sep 13 olle 141             if (otherBloodSuffixIndex >= 0)
2023 19 Sep 13 olle 142             {
2023 19 Sep 13 olle 143               caseName = otherBloodName.substring(0, otherBloodSuffixIndex);
2023 19 Sep 13 olle 144             }
2023 19 Sep 13 olle 145           }          
2023 19 Sep 13 olle 146         }
2023 19 Sep 13 olle 147
2023 19 Sep 13 olle 148         // Connect the follow-up blood information if we have any
2023 19 Sep 13 olle 149         if (blood != null)
2023 19 Sep 13 olle 150         {
2023 19 Sep 13 olle 151           JSONObject jsonBlood = new JSONObject();
2023 19 Sep 13 olle 152           jsonBlood = blood.asJSONObject();
2602 27 Aug 14 nicklas 153           json.put("bloodInfo", jsonBlood);
2023 19 Sep 13 olle 154         }
2023 19 Sep 13 olle 155         
2023 19 Sep 13 olle 156         // Connect the patient information if we have any
2023 19 Sep 13 olle 157         if (patient != null)
2023 19 Sep 13 olle 158         {
2023 19 Sep 13 olle 159           patient.loadDefaultAnnotations(dc);
2023 19 Sep 13 olle 160           json.put("patientInfo", patient.asJSONObject());
2023 19 Sep 13 olle 161         }
2023 19 Sep 13 olle 162         
2023 19 Sep 13 olle 163         // Connect the case information if we have any
2602 27 Aug 14 nicklas 164         if (caseName != null)
2023 19 Sep 13 olle 165         {
2602 27 Aug 14 nicklas 166           Case theCase = Case.findByName(dc, caseName);
2602 27 Aug 14 nicklas 167           json.put("caseInfo", theCase.asJSONObject());
2023 19 Sep 13 olle 168         }        
2023 19 Sep 13 olle 169       }
2602 27 Aug 14 nicklas 170       else if ("GetNextBloodName".equals(cmd))
2023 19 Sep 13 olle 171       {
2023 19 Sep 13 olle 172         /*
2602 27 Aug 14 nicklas 173           Generate name for the next blood sample for a given case
2023 19 Sep 13 olle 174         */
6329 14 Jun 21 nicklas 175         dc = sc.newDbControl(":Follow-up blood referral form registration");
2023 19 Sep 13 olle 176         
2602 27 Aug 14 nicklas 177         int caseId = Values.getInt(req.getParameter("caseId"));
2023 19 Sep 13 olle 178         Patient patient = null;
2023 19 Sep 13 olle 179         JSONObject jsonBlood = null;
2023 19 Sep 13 olle 180         
2602 27 Aug 14 nicklas 181         Case theCase = Case.getById(dc, caseId);
4900 10 Jul 18 nicklas 182         String bloodName = Blood.getNextBloodName(dc, theCase.getName());
2602 27 Aug 14 nicklas 183         jsonBlood = new JSONObject();
2602 27 Aug 14 nicklas 184         jsonBlood.put("name", bloodName);
2023 19 Sep 13 olle 185         json.put("bloodInfo", jsonBlood);
2602 27 Aug 14 nicklas 186         Consent.loadConsentAnnotations(dc, theCase);
2602 27 Aug 14 nicklas 187         json.put("consentInfo", theCase.asJSONObject());
2023 19 Sep 13 olle 188         
2023 19 Sep 13 olle 189       }
2602 27 Aug 14 nicklas 190       else if ("GetCaseOptions".equals(cmd))
2023 19 Sep 13 olle 191       {
6329 14 Jun 21 nicklas 192         dc = sc.newDbControl(":Follow-up blood referral form registration");
2023 19 Sep 13 olle 193         // Use stored annotation snapshots for performance reasons
2023 19 Sep 13 olle 194         SnapshotManager manager = new SnapshotManager();        
2023 19 Sep 13 olle 195         
2023 19 Sep 13 olle 196         // Find cases by personal number
2023 19 Sep 13 olle 197         List<Case> caseList = null;
2023 19 Sep 13 olle 198         List<Case> bloodFollowUpCaseList = new ArrayList<Case>();
2023 19 Sep 13 olle 199         List<Case> bloodNotFollowUpCaseList = new ArrayList<Case>();
2023 19 Sep 13 olle 200         List<Case> noBloodCaseList = new ArrayList<Case>();
2023 19 Sep 13 olle 201
6801 11 Aug 22 nicklas 202         int patientId = Values.getInt(req.getParameter("patientId"));
2602 27 Aug 14 nicklas 203         int caseId = Values.getInt(req.getParameter("caseId"));
6801 11 Aug 22 nicklas 204         Patient patient = Patient.getById(dc, patientId);
2023 19 Sep 13 olle 205         if (patient != null)
2023 19 Sep 13 olle 206         {
2023 19 Sep 13 olle 207           caseList = Case.findByPatient(dc, patient);
2023 19 Sep 13 olle 208         }
2023 19 Sep 13 olle 209         if (caseList != null)
2023 19 Sep 13 olle 210         {
2023 19 Sep 13 olle 211           List<Sample> rawSampleList = new ArrayList<Sample>();
2023 19 Sep 13 olle 212           for (Case caseItem: caseList)
2023 19 Sep 13 olle 213           {
2602 27 Aug 14 nicklas 214             // Ignore if not equal to given case id
2602 27 Aug 14 nicklas 215             if (caseId != 0 && caseItem.getItem().getId() != caseId) continue;
6153 26 Feb 21 nicklas 216             // Get list of specimen, "no specimen" and "future specimen" samples for case
2023 19 Sep 13 olle 217             List<Sample> caseSampleList = getSpecimenNoSpecimenSamples(dc, caseItem);
2023 19 Sep 13 olle 218             for (Sample s: caseSampleList)
2023 19 Sep 13 olle 219             {
2023 19 Sep 13 olle 220               rawSampleList.add(s);
2023 19 Sep 13 olle 221             }
2602 27 Aug 14 nicklas 222
2023 19 Sep 13 olle 223             // Find all blood samples for case
2023 19 Sep 13 olle 224             List<Blood> bloodList = Blood.findAllByCaseName(dc, caseItem.getName());
2023 19 Sep 13 olle 225             if (bloodList == null || bloodList.size() == 0)
2023 19 Sep 13 olle 226             {
2023 19 Sep 13 olle 227               noBloodCaseList.add(caseItem);
2023 19 Sep 13 olle 228             }
2023 19 Sep 13 olle 229             else
2023 19 Sep 13 olle 230             {
2023 19 Sep 13 olle 231               // Check if any blood items are follow-up samples
2023 19 Sep 13 olle 232               for (Blood blood: bloodList)
2023 19 Sep 13 olle 233               {
2023 19 Sep 13 olle 234                 // Get blood sample annotation
2023 19 Sep 13 olle 235                 String bloodSampleType = (String) Annotationtype.BLOOD_SAMPLE.getAnnotationValue(dc, manager, blood.getSample());
2023 19 Sep 13 olle 236                 
2023 19 Sep 13 olle 237                 if (bloodSampleType != null &&
2023 19 Sep 13 olle 238                     (bloodSampleType.equals(BLOOD_FILTER_FOLLOW_UP_06)
2023 19 Sep 13 olle 239                     || bloodSampleType.equals(BLOOD_FILTER_FOLLOW_UP_12)
2023 19 Sep 13 olle 240                     || bloodSampleType.equals(BLOOD_FILTER_FOLLOW_UP_36))
2023 19 Sep 13 olle 241                   )
2023 19 Sep 13 olle 242                 {
2023 19 Sep 13 olle 243                   if (!bloodFollowUpCaseList.contains(caseItem))
2023 19 Sep 13 olle 244                   {
2023 19 Sep 13 olle 245                     bloodFollowUpCaseList.add(caseItem);
2023 19 Sep 13 olle 246                   }
2023 19 Sep 13 olle 247                 }
2023 19 Sep 13 olle 248                 else
2023 19 Sep 13 olle 249                 {
2023 19 Sep 13 olle 250                   if (!bloodNotFollowUpCaseList.contains(caseItem))
2023 19 Sep 13 olle 251                   {
2023 19 Sep 13 olle 252                     bloodNotFollowUpCaseList.add(caseItem);
2023 19 Sep 13 olle 253                   }
2023 19 Sep 13 olle 254                 }
2023 19 Sep 13 olle 255               }
2023 19 Sep 13 olle 256               if (!bloodFollowUpCaseList.contains(caseItem))
2023 19 Sep 13 olle 257               {
2023 19 Sep 13 olle 258                 bloodNotFollowUpCaseList.add(caseItem);
2023 19 Sep 13 olle 259               }
2023 19 Sep 13 olle 260             }
2023 19 Sep 13 olle 261           }
2023 19 Sep 13 olle 262           // Sort each case list after case name
2023 19 Sep 13 olle 263           List<Case> bloodFollowUpCaseListSorted = createCaseOrderedList(bloodFollowUpCaseList);
2023 19 Sep 13 olle 264           List<Case> bloodNotFollowUpCaseListSorted = createCaseOrderedList(bloodNotFollowUpCaseList);
2023 19 Sep 13 olle 265           List<Case> noBloodCaseListSorted = createCaseOrderedList(noBloodCaseList);
2023 19 Sep 13 olle 266           // Create JSON array with case options
2023 19 Sep 13 olle 267           JSONArray jsonCaseOptionArray = new JSONArray();
7024 07 Feb 23 nicklas 268           DateToStringConverter dateFormat = new DateToStringConverter(FastDateFormat.getInstance("yyyy-MM-dd"));
2023 19 Sep 13 olle 269           for (Case caseItem: bloodFollowUpCaseListSorted)
2023 19 Sep 13 olle 270           {
2023 19 Sep 13 olle 271             // Construct case option name as case name + operation date + blood sample status
2023 19 Sep 13 olle 272             String caseOptionName = getCaseOption(rawSampleList, caseItem, dateFormat);
2023 19 Sep 13 olle 273             caseOptionName += "; follow-up blood sample";
2023 19 Sep 13 olle 274             JSONObject jsonOption = new JSONObject();
2602 27 Aug 14 nicklas 275             jsonOption.put("id", caseItem.getItem().getId());
2023 19 Sep 13 olle 276             jsonOption.put("text", caseOptionName);
2023 19 Sep 13 olle 277             jsonCaseOptionArray.add(jsonOption);
2023 19 Sep 13 olle 278
2023 19 Sep 13 olle 279           }
2023 19 Sep 13 olle 280           for (Case caseItem: bloodNotFollowUpCaseListSorted)
2023 19 Sep 13 olle 281           {
2023 19 Sep 13 olle 282             // Ignore case if already included in list with higher priority
2023 19 Sep 13 olle 283             if (bloodFollowUpCaseListSorted.contains(caseItem))
2023 19 Sep 13 olle 284             {
2023 19 Sep 13 olle 285               continue;
2023 19 Sep 13 olle 286             }
2023 19 Sep 13 olle 287             // Construct case option name as case name + operation date + blood sample status
2023 19 Sep 13 olle 288             String caseOptionName = getCaseOption(rawSampleList, caseItem, dateFormat);
2023 19 Sep 13 olle 289             caseOptionName += "; not follow-up blood sample";
2023 19 Sep 13 olle 290             JSONObject jsonOption = new JSONObject();
2602 27 Aug 14 nicklas 291             jsonOption.put("id", caseItem.getItem().getId());
2023 19 Sep 13 olle 292             jsonOption.put("text", caseOptionName);
2023 19 Sep 13 olle 293             jsonCaseOptionArray.add(jsonOption);
2023 19 Sep 13 olle 294           }
2023 19 Sep 13 olle 295           for (Case caseItem: noBloodCaseListSorted)
2023 19 Sep 13 olle 296           {
2023 19 Sep 13 olle 297             // Ignore case if already included in list with higher priority
2023 19 Sep 13 olle 298             if (bloodFollowUpCaseListSorted.contains(caseItem)
2023 19 Sep 13 olle 299               || bloodNotFollowUpCaseListSorted.contains(caseItem))
2023 19 Sep 13 olle 300             {
2023 19 Sep 13 olle 301               continue;
2023 19 Sep 13 olle 302             }
2023 19 Sep 13 olle 303             // Construct case option name as case name + operation date + blood sample status
2023 19 Sep 13 olle 304             String caseOptionName = getCaseOption(rawSampleList, caseItem, dateFormat);
2023 19 Sep 13 olle 305             caseOptionName += "; no blood sample";
2023 19 Sep 13 olle 306             JSONObject jsonOption = new JSONObject();
2602 27 Aug 14 nicklas 307             jsonOption.put("id", caseItem.getItem().getId());
2023 19 Sep 13 olle 308             jsonOption.put("text", caseOptionName);
2023 19 Sep 13 olle 309             jsonCaseOptionArray.add(jsonOption);
2023 19 Sep 13 olle 310           }
2023 19 Sep 13 olle 311           json.put("caseOptionArray", jsonCaseOptionArray);
2023 19 Sep 13 olle 312         }
2023 19 Sep 13 olle 313       }
2023 19 Sep 13 olle 314     }
2023 19 Sep 13 olle 315     catch (Throwable t)
2023 19 Sep 13 olle 316     {
2023 19 Sep 13 olle 317       t.printStackTrace();
2023 19 Sep 13 olle 318       json.clear();
2023 19 Sep 13 olle 319       json.put("status", "error");
2023 19 Sep 13 olle 320       json.put("message", t.getMessage());
2023 19 Sep 13 olle 321       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
2023 19 Sep 13 olle 322     }
2023 19 Sep 13 olle 323     finally
2023 19 Sep 13 olle 324     {
2023 19 Sep 13 olle 325       if (dc != null) dc.close();
2023 19 Sep 13 olle 326       json.writeJSONString(resp.getWriter());
2023 19 Sep 13 olle 327     }
2023 19 Sep 13 olle 328   }
2023 19 Sep 13 olle 329
2023 19 Sep 13 olle 330   /**
2023 19 Sep 13 olle 331    *  Get a case option string for a case.
2023 19 Sep 13 olle 332    *
2023 19 Sep 13 olle 333    *  @param rawSampleList List<Sample> List of specimen and "no specimen" items.
2023 19 Sep 13 olle 334    *  @param caseItem Case The case item to get samples for.
2023 19 Sep 13 olle 335    *  @return List<Sample> List of specimen and "no specimen" items for the given case.
2023 19 Sep 13 olle 336    */
2023 19 Sep 13 olle 337   public String getCaseOption(List<Sample> rawSampleList, Case caseItem, DateToStringConverter dateFormat)
2023 19 Sep 13 olle 338   {
2023 19 Sep 13 olle 339     if (caseItem == null)
2023 19 Sep 13 olle 340     {
2023 19 Sep 13 olle 341       return null;
2023 19 Sep 13 olle 342     }
2023 19 Sep 13 olle 343     // Construct case option name as case name + operation date + blood sample status
2023 19 Sep 13 olle 344     String caseOptionName = caseItem.getName();
2023 19 Sep 13 olle 345     // Find all specimen and "no specimen" samples for this case
2023 19 Sep 13 olle 346     List<Sample> sampleList = new ArrayList<Sample>();
2023 19 Sep 13 olle 347     for (Sample s: rawSampleList)
2023 19 Sep 13 olle 348     {
2023 19 Sep 13 olle 349       // Case name equals the sample name before first "."
2023 19 Sep 13 olle 350       String sampleCaseName = s.getName();
2023 19 Sep 13 olle 351       int dotIndex = s.getName().indexOf(".");
2023 19 Sep 13 olle 352       if (dotIndex >= 0)
2023 19 Sep 13 olle 353       {
2023 19 Sep 13 olle 354         sampleCaseName = s.getName().substring(0, dotIndex);
2023 19 Sep 13 olle 355       }
2023 19 Sep 13 olle 356       if (sampleCaseName.equals(caseOptionName))
2023 19 Sep 13 olle 357       {
2023 19 Sep 13 olle 358         sampleList.add(s);
2023 19 Sep 13 olle 359       }
2023 19 Sep 13 olle 360     }
2023 19 Sep 13 olle 361     // Find all operation dates for the given case and sort them
2023 19 Sep 13 olle 362     List<Date> operationDateList = new ArrayList<Date>();
2023 19 Sep 13 olle 363     for (Sample s: sampleList)
2023 19 Sep 13 olle 364     {
2023 19 Sep 13 olle 365       Date date = s.getCreationEvent().getEventDate();
2634 03 Sep 14 nicklas 366       if (date != null) operationDateList.add(date);
2023 19 Sep 13 olle 367     }
2023 19 Sep 13 olle 368     Collections.sort(operationDateList);
2023 19 Sep 13 olle 369     caseOptionName += " opdate(s) = ";
2023 19 Sep 13 olle 370     if (operationDateList.size() > 0)
2023 19 Sep 13 olle 371     {
2023 19 Sep 13 olle 372       int NumOpDates = 0;
2023 19 Sep 13 olle 373       for (Date date: operationDateList)
2023 19 Sep 13 olle 374       {
2023 19 Sep 13 olle 375         if (NumOpDates > 0)
2023 19 Sep 13 olle 376         {
2023 19 Sep 13 olle 377           caseOptionName += ", ";
2023 19 Sep 13 olle 378         }
2023 19 Sep 13 olle 379         NumOpDates++;
2023 19 Sep 13 olle 380         String opDateStr = dateFormat.convert(date);
2023 19 Sep 13 olle 381         caseOptionName += opDateStr;
2023 19 Sep 13 olle 382       }
2023 19 Sep 13 olle 383     }
2023 19 Sep 13 olle 384     else
2023 19 Sep 13 olle 385     {
2023 19 Sep 13 olle 386       caseOptionName += "unknown";
2023 19 Sep 13 olle 387     }
2023 19 Sep 13 olle 388     return caseOptionName;
2023 19 Sep 13 olle 389   }
2023 19 Sep 13 olle 390   
2023 19 Sep 13 olle 391   /**
2023 19 Sep 13 olle 392    *  Get a list of specimen and "no specimen" items for a case.
2023 19 Sep 13 olle 393    *
2023 19 Sep 13 olle 394    *  @param dc DbControl The DbControl to use.
3571 30 Oct 15 nicklas 395    *  @param caseItem Case The case to get samples for.
2023 19 Sep 13 olle 396    *  @return List<Sample> List of specimen and "no specimen" items for the patient.
2023 19 Sep 13 olle 397    */
2023 19 Sep 13 olle 398   public List<Sample> getSpecimenNoSpecimenSamples(DbControl dc, Case caseItem)
2023 19 Sep 13 olle 399   {
2023 19 Sep 13 olle 400     ItemQuery<Sample> sampleQuery = caseItem.getSample().getChildSamples();
2023 19 Sep 13 olle 401     sampleQuery.joinPermanent(Hql.innerJoin(null, "creationEvent", "ce", true));
2023 19 Sep 13 olle 402     // ...only include 'Specimen' and 'No specimen' items
2023 19 Sep 13 olle 403     sampleQuery.restrict(
2023 19 Sep 13 olle 404       Restrictions.or(
2023 19 Sep 13 olle 405         Subtype.SPECIMEN.restriction(dc, null),
6510 03 Dec 21 nicklas 406         Subtype.NO_SPECIMEN.restriction(dc, null)
2023 19 Sep 13 olle 407       ));
2023 19 Sep 13 olle 408     sampleQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
2023 19 Sep 13 olle 409     sampleQuery.order(Orders.asc(Hql.property("name")));
2023 19 Sep 13 olle 410     sampleQuery.order(Orders.asc(Hql.property("ce", "eventDate")));
2023 19 Sep 13 olle 411     sampleQuery.setCacheResult(true);
2023 19 Sep 13 olle 412     // Perform database query and get list of all raw samples
2023 19 Sep 13 olle 413     List<Sample> sampleList = new ArrayList<Sample>();
2023 19 Sep 13 olle 414     for (Sample s: sampleQuery.list(dc))
2023 19 Sep 13 olle 415     {
2023 19 Sep 13 olle 416       sampleList.add(s);
2023 19 Sep 13 olle 417     }
2023 19 Sep 13 olle 418     return sampleList;
2023 19 Sep 13 olle 419   }
2023 19 Sep 13 olle 420
2023 19 Sep 13 olle 421   /**
2023 19 Sep 13 olle 422    *  Creates a list of cases sorted after case names.
2023 19 Sep 13 olle 423    *
3571 30 Oct 15 nicklas 424    *  @param inputCaseList List<Case> Case list to be sorted.
2023 19 Sep 13 olle 425    *  @return List<Case> List of cases sorted after case names.
2023 19 Sep 13 olle 426    */
2023 19 Sep 13 olle 427   @SuppressWarnings("rawtypes")
2023 19 Sep 13 olle 428   public List<Case> createCaseOrderedList(List<Case> inputCaseList)
2023 19 Sep 13 olle 429   {
2023 19 Sep 13 olle 430     if (inputCaseList == null)
2023 19 Sep 13 olle 431     {
2023 19 Sep 13 olle 432       return null;
2023 19 Sep 13 olle 433     }
2023 19 Sep 13 olle 434     TreeMap<Comparable, Case> treeMap = new TreeMap<Comparable, Case>();
2023 19 Sep 13 olle 435     for (Case caseItem: inputCaseList)
2023 19 Sep 13 olle 436     {
2023 19 Sep 13 olle 437       Comparable comparableObject = caseItem.getName();
2023 19 Sep 13 olle 438       treeMap.put(comparableObject, caseItem);
2023 19 Sep 13 olle 439     }
2023 19 Sep 13 olle 440     List<Case> caseList = new ArrayList<Case>();
2023 19 Sep 13 olle 441     for (Comparable key: treeMap.keySet())
2023 19 Sep 13 olle 442     {
2023 19 Sep 13 olle 443       caseList.add(treeMap.get(key));
2023 19 Sep 13 olle 444     } 
2023 19 Sep 13 olle 445     return caseList;
2023 19 Sep 13 olle 446   }
2023 19 Sep 13 olle 447
2023 19 Sep 13 olle 448   @Override
2023 19 Sep 13 olle 449   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
2023 19 Sep 13 olle 450     throws ServletException, IOException 
2023 19 Sep 13 olle 451   {
2023 19 Sep 13 olle 452     String cmd = req.getParameter("cmd");
2598 22 Aug 14 nicklas 453     JsonUtil.setJsonResponseHeaders(resp);
2023 19 Sep 13 olle 454     
2023 19 Sep 13 olle 455     JSONObject json = new JSONObject();
2023 19 Sep 13 olle 456     json.put("status", "ok");
2023 19 Sep 13 olle 457     
2023 19 Sep 13 olle 458     JSONArray jsonMessages = new JSONArray();
2023 19 Sep 13 olle 459   
3975 26 May 16 nicklas 460     final SessionControl sc = Reggie.getSessionControl(req);
2023 19 Sep 13 olle 461     DbControl dc = null;
2023 19 Sep 13 olle 462     try
2023 19 Sep 13 olle 463     {
2023 19 Sep 13 olle 464       if ("CreateBlood".equals(cmd))
2023 19 Sep 13 olle 465       {
6329 14 Jun 21 nicklas 466         dc = sc.newDbControl(":Follow-up blood referral form registration");
2161 09 Dec 13 nicklas 467
2161 09 Dec 13 nicklas 468         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
2161 09 Dec 13 nicklas 469
3752 17 Feb 16 nicklas 470         JSONObject jsonReq = JsonUtil.parseRequest(req);
2023 19 Sep 13 olle 471         JSONObject jsonPat = (JSONObject)jsonReq.get("patientInfo");
2023 19 Sep 13 olle 472         JSONObject jsonBlood = (JSONObject)jsonReq.get("bloodInfo");
2023 19 Sep 13 olle 473         
4072 02 Sep 16 nicklas 474         Number patientId = (Number)jsonPat.get("id");
4072 02 Sep 16 nicklas 475         BioSource patient = BioSource.getById(dc, patientId.intValue());
2023 19 Sep 13 olle 476                   
2023 19 Sep 13 olle 477         // Load/create blood
2023 19 Sep 13 olle 478         String bloodName = (String)jsonBlood.get("name");
2023 19 Sep 13 olle 479         Sample blood = Sample.getNew(dc);
2023 19 Sep 13 olle 480         blood.setItemSubtype(Subtype.BLOOD.load(dc));
4900 10 Jul 18 nicklas 481         blood.setName(ReggieItem.ensureNonExistingItem(dc, Subtype.BLOOD, bloodName));
4902 10 Jul 18 nicklas 482         blood.setExternalId(Blood.getNextExternalId(dc));
2023 19 Sep 13 olle 483         BioMaterialEvent creationEvent = blood.getCreationEvent();
2023 19 Sep 13 olle 484         creationEvent.setSource(patient);
2023 19 Sep 13 olle 485         dc.saveItem(blood);
2023 19 Sep 13 olle 486
2023 19 Sep 13 olle 487         // Annotations
2023 19 Sep 13 olle 488         String rccidNumber = Values.getStringOrNull((String)jsonBlood.get("rccidNumber"));
2023 19 Sep 13 olle 489         Date samplingDate = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonBlood.get("samplingDate"));
2023 19 Sep 13 olle 490         Date freezerDate = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonBlood.get("freezerDate"));
2023 19 Sep 13 olle 491         String bloodSample = Values.getStringOrNull((String)jsonBlood.get("bloodSample"));
2023 19 Sep 13 olle 492         String otherPathNote = Values.getStringOrNull((String)jsonBlood.get("otherPathNote"));
2023 19 Sep 13 olle 493         
2023 19 Sep 13 olle 494         creationEvent.setEventDate(samplingDate);
2023 19 Sep 13 olle 495         Annotationtype.BLOOD_RCCIDNUMBER.setAnnotationValue(dc, blood, rccidNumber);
2023 19 Sep 13 olle 496         Annotationtype.BLOOD_SAMPLING_DATETIME.setAnnotationValue(dc, blood, samplingDate);
2023 19 Sep 13 olle 497         Annotationtype.BLOOD_FREEZER_DATETIME.setAnnotationValue(dc, blood, freezerDate);
2023 19 Sep 13 olle 498         Annotationtype.BLOOD_SERUM.setAnnotationValue(dc, blood, jsonBlood.get("serum"));
2023 19 Sep 13 olle 499         Annotationtype.BLOOD_SAMPLE.setAnnotationValue(dc, blood, bloodSample);
2023 19 Sep 13 olle 500         Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, blood, otherPathNote);
2023 19 Sep 13 olle 501
2023 19 Sep 13 olle 502         Number copyConsentId = (Number)jsonBlood.get("copyConsent");
2023 19 Sep 13 olle 503         if (copyConsentId != null)
2023 19 Sep 13 olle 504         {
2023 19 Sep 13 olle 505           Sample consentCase = Sample.getById(dc, copyConsentId.intValue());
5277 05 Feb 19 nicklas 506           Consent.copyConsentAnnotations(dc, consentCase, blood, true);
2023 19 Sep 13 olle 507           if (consentCase.getParentType() == null)
2023 19 Sep 13 olle 508           {
2023 19 Sep 13 olle 509             // Temporary case for holding consent information that should deleted
2023 19 Sep 13 olle 510             dc.deleteItem(consentCase);
2023 19 Sep 13 olle 511           }
2023 19 Sep 13 olle 512           jsonMessages.add("Consent copied from case '" + consentCase.getName() + "'");
2023 19 Sep 13 olle 513         }
2023 19 Sep 13 olle 514         
2023 19 Sep 13 olle 515         jsonMessages.add("Blood '" + bloodName + "' created successfully.");
2023 19 Sep 13 olle 516         
5421 13 May 19 nicklas 517         ActivityDef.REGISTERED_FOLLOWUP_BLOOD.merge(dc, 1);
2023 19 Sep 13 olle 518         
2023 19 Sep 13 olle 519         dc.commit();
2023 19 Sep 13 olle 520       }
2023 19 Sep 13 olle 521       else if ("UpdateBlood".equals(cmd))
2023 19 Sep 13 olle 522       {
6329 14 Jun 21 nicklas 523         dc = sc.newDbControl(":Follow-up blood referral form registration");
2161 09 Dec 13 nicklas 524
2161 09 Dec 13 nicklas 525         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
2161 09 Dec 13 nicklas 526
3752 17 Feb 16 nicklas 527         JSONObject jsonReq = JsonUtil.parseRequest(req);
2023 19 Sep 13 olle 528         JSONObject jsonBlood = (JSONObject)jsonReq.get("bloodInfo");
2023 19 Sep 13 olle 529         
2023 19 Sep 13 olle 530         Number bloodId = (Number)jsonBlood.get("id");
2023 19 Sep 13 olle 531         Sample blood = Sample.getById(dc, bloodId.intValue());
2023 19 Sep 13 olle 532         
2023 19 Sep 13 olle 533         // Annotations
2023 19 Sep 13 olle 534         String rccidNumber = Values.getStringOrNull((String)jsonBlood.get("rccidNumber"));
2023 19 Sep 13 olle 535         Date samplingDate = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonBlood.get("samplingDate"));
2023 19 Sep 13 olle 536         Date freezerDate = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonBlood.get("freezerDate"));
2023 19 Sep 13 olle 537         String bloodSample = Values.getStringOrNull((String)jsonBlood.get("bloodSample"));
2023 19 Sep 13 olle 538         String otherPathNote = Values.getStringOrNull((String)jsonBlood.get("otherPathNote"));
2023 19 Sep 13 olle 539         
2023 19 Sep 13 olle 540         blood.getCreationEvent().setEventDate(samplingDate);
2023 19 Sep 13 olle 541         
2023 19 Sep 13 olle 542         Annotationtype.BLOOD_RCCIDNUMBER.setAnnotationValue(dc, blood, rccidNumber);
2023 19 Sep 13 olle 543         Annotationtype.BLOOD_SAMPLING_DATETIME.setAnnotationValue(dc, blood, samplingDate);
2023 19 Sep 13 olle 544         Annotationtype.BLOOD_FREEZER_DATETIME.setAnnotationValue(dc, blood, freezerDate);
2023 19 Sep 13 olle 545         Annotationtype.BLOOD_SERUM.setAnnotationValue(dc, blood, jsonBlood.get("serum"));
2023 19 Sep 13 olle 546         Annotationtype.BLOOD_SAMPLE.setAnnotationValue(dc, blood, bloodSample);
2023 19 Sep 13 olle 547         Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, blood, otherPathNote);
2023 19 Sep 13 olle 548
2023 19 Sep 13 olle 549         jsonMessages.add("Blood '" + blood.getName() + "' updated successfully.");
2023 19 Sep 13 olle 550                 
2023 19 Sep 13 olle 551         dc.commit();
2023 19 Sep 13 olle 552       }
5910 17 Apr 20 nicklas 553       else if ("BatchImportFromFile".equals(cmd))
5910 17 Apr 20 nicklas 554       {
5910 17 Apr 20 nicklas 555         
5910 17 Apr 20 nicklas 556         boolean validateOnly = Values.getBoolean(req.getParameter("validateOnly"));
5910 17 Apr 20 nicklas 557         String filename = Values.getString(req.getParameter("filename"), "");
5910 17 Apr 20 nicklas 558         String sheet = Values.getStringOrNull(req.getParameter("sheet"));
5910 17 Apr 20 nicklas 559         
6329 14 Jun 21 nicklas 560         dc = sc.newDbControl(":Follow-up blood batch registration");
5919 24 Apr 20 nicklas 561         ProgressReporter progress = new AbortableProgressReporter(null);
5910 17 Apr 20 nicklas 562         if (!validateOnly)
5910 17 Apr 20 nicklas 563         {
5910 17 Apr 20 nicklas 564           ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
5916 22 Apr 20 nicklas 565           sc.setSessionSetting("follow-up-import-progress", progress);
5910 17 Apr 20 nicklas 566         }
5910 17 Apr 20 nicklas 567         
5910 17 Apr 20 nicklas 568         FollowupBloodImporter importer = new FollowupBloodImporter();
5916 22 Apr 20 nicklas 569         boolean valid = importer.doImport(dc, req.getInputStream(), sheet, validateOnly, filename, progress);
5916 22 Apr 20 nicklas 570         int numValid = importer.getNumValidEntries();
5910 17 Apr 20 nicklas 571         List<String> sheetNames = importer.getWorksheets();
5910 17 Apr 20 nicklas 572         if (sheetNames != null) 
5910 17 Apr 20 nicklas 573         {
5910 17 Apr 20 nicklas 574           json.put("sheetNames", sheetNames);
5910 17 Apr 20 nicklas 575           filename += "/" + importer.getParsedWorksheet();
5910 17 Apr 20 nicklas 576         }
5916 22 Apr 20 nicklas 577         
5916 22 Apr 20 nicklas 578         if (valid && !validateOnly)
5916 22 Apr 20 nicklas 579         {
5916 22 Apr 20 nicklas 580           int numCreated = importer.getNumCreated();
5916 22 Apr 20 nicklas 581           int numExisting = importer.getNumExisting();
5916 22 Apr 20 nicklas 582           if (numCreated > 0)
5916 22 Apr 20 nicklas 583           {
5916 22 Apr 20 nicklas 584             progress.display(95, "Saving " + numCreated + " new entries; " + numExisting + " already existed...");
5916 22 Apr 20 nicklas 585           }
5916 22 Apr 20 nicklas 586           
5916 22 Apr 20 nicklas 587           dc.commit();
5916 22 Apr 20 nicklas 588           progress.display(100, "Import complete. " + numValid + " entries processed; " + numCreated + " new; " + numExisting + " already existed.");
5916 22 Apr 20 nicklas 589         }
5910 17 Apr 20 nicklas 590
5910 17 Apr 20 nicklas 591         if (valid)
5910 17 Apr 20 nicklas 592         {
5916 22 Apr 20 nicklas 593           jsonMessages.add("Found " + numValid + " entries in " + filename);
5916 22 Apr 20 nicklas 594           if (!validateOnly)
5916 22 Apr 20 nicklas 595           {
5916 22 Apr 20 nicklas 596             jsonMessages.add(importer.getNumCreated() + " new entries created");
5916 22 Apr 20 nicklas 597             jsonMessages.add(importer.getNumExisting() + " entries already existed");
5916 22 Apr 20 nicklas 598           }
5917 23 Apr 20 nicklas 599           json.put("numWarnings", importer.getWarningMessages().size());
5917 23 Apr 20 nicklas 600           jsonMessages.addAll(importer.getWarningMessages());
5910 17 Apr 20 nicklas 601         }
5910 17 Apr 20 nicklas 602         else
5910 17 Apr 20 nicklas 603         {
5917 23 Apr 20 nicklas 604           int numInvalid = importer.getNumEntries() - numValid;
5931 06 May 20 nicklas 605           if (numInvalid > 0)
5916 22 Apr 20 nicklas 606           {
5931 06 May 20 nicklas 607             String invalidEntries = numInvalid + " of " + importer.getNumEntries() + " entries in file " + filename + " are invalid.";
5931 06 May 20 nicklas 608             if (validateOnly)
5931 06 May 20 nicklas 609             {
5931 06 May 20 nicklas 610               jsonMessages.add("[Error]Validation failed. " + invalidEntries);
5931 06 May 20 nicklas 611             }
5931 06 May 20 nicklas 612             else
5931 06 May 20 nicklas 613             {
5931 06 May 20 nicklas 614               jsonMessages.add("[Error]Import failed. " + invalidEntries);
5931 06 May 20 nicklas 615             }
5916 22 Apr 20 nicklas 616           }
5916 22 Apr 20 nicklas 617           
5931 06 May 20 nicklas 618           json.put("numErrors", importer.getErrorMessages().size());
5931 06 May 20 nicklas 619           jsonMessages.addAll(importer.getErrorMessages());
5931 06 May 20 nicklas 620
5917 23 Apr 20 nicklas 621           json.put("numWarnings", importer.getWarningMessages().size());
5917 23 Apr 20 nicklas 622           jsonMessages.addAll(importer.getWarningMessages());
5910 17 Apr 20 nicklas 623         }
5910 17 Apr 20 nicklas 624       }
5910 17 Apr 20 nicklas 625       json.put("messages", jsonMessages);
3059 19 Dec 14 nicklas 626       CounterService.getInstance().setForceCount();
2023 19 Sep 13 olle 627     }
2023 19 Sep 13 olle 628     catch (Throwable t)
2023 19 Sep 13 olle 629     {
2023 19 Sep 13 olle 630       t.printStackTrace();
2023 19 Sep 13 olle 631       json.clear();
2023 19 Sep 13 olle 632       json.put("status", "error");
2023 19 Sep 13 olle 633       json.put("message", t.getMessage());
2023 19 Sep 13 olle 634       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
2023 19 Sep 13 olle 635     }
2023 19 Sep 13 olle 636     finally
2023 19 Sep 13 olle 637     {
2023 19 Sep 13 olle 638       if (dc != null) dc.close();
2023 19 Sep 13 olle 639       json.writeJSONString(resp.getWriter());
2023 19 Sep 13 olle 640     }
2023 19 Sep 13 olle 641     
2023 19 Sep 13 olle 642   }
2023 19 Sep 13 olle 643
2023 19 Sep 13 olle 644 }