Changeset 1333


Ignore:
Timestamp:
Apr 5, 2011, 11:29:33 AM (10 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #302: Update functionality in the Personal information registration

The create and update paths have been made more similar to reduce the number of special cases that the code needs to handle. Basically, as much info as we can is extracted from the case (if it exists) and specimen tubes in step 1. This information is used in step 3 and the user can accept it as it is, add missing information or change the current information.

There are some exotic cases that are still problematic. For example, it is not always possible to relate PAD to a case without specimen tubes if there is more than one case for a patient.

Also updated the index page to make it look better.

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
5 added
8 edited

Legend:

Unmodified
Added
Removed
  • extensions/net.sf.basedb.reggie/trunk/resources/index.jsp

    r1288 r1333  
    5353<base:page type="default" >
    5454<base:head styles="path.css">
     55<style>
     56dd
     57{
     58  margin-left: 0px;
     59  margin-bottom: 10px;
     60}
     61</style>
    5562</base:head>
    5663<base:body>
     
    6673    <h3 class="light">Reggie wizards</h3>
    6774    <div class="boxedbottom">
    68       <ul>
     75      <dl>
     76     
    6977      <%
    7078      if (isAdmin)
    7179      {
    7280        %>
    73         <li><a href="install.jsp?ID=<%=ID%>">Verify/install required annotation types and other items</a>
     81        <dt>
     82          <table border="0" cellspacing="0" cellpadding="0">
     83          <tr>
     84            <td><base:icon image="configure.png" style="padding-right: 4px;"/></td>
     85            <td><a href="install.jsp?ID=<%=ID%>">Installation wizard</a></td>
     86          </tr>
     87          </table>
     88        </dt>
     89        <dd>
     90          <ul>
     91          <li>Check that all annotation types and other items used by Reggies exists in BASE.
     92          <li>Create missing items.
     93          </ul>
     94        </dd>
    7495        <%
    7596      }
     
    7798      {
    7899        %>
    79         <li><a href="persinfo.jsp?ID=<%=ID%>">Personal information registration</a>
     100        <dt>
     101          <table border="0" cellspacing="0" cellpadding="0">
     102          <tr>
     103            <td><base:icon image="share.gif" style="padding-right: 4px;"/></td>
     104            <td><a href="persinfo.jsp?ID=<%=ID%>">Personal information registration wizard</a></td>
     105          </tr>
     106          </table>
     107        </dt>
     108        <dd>
     109          <ul>
     110          <li>Register new cases and patients.
     111          <li>Update existing cases and specimen tubes.
     112          </ul>
     113        </dd>
    80114        <%
    81115      }
    82116      %>
    83       </ul>
     117      </dl>
    84118   
    85119    </div>
  • extensions/net.sf.basedb.reggie/trunk/resources/install.jsp

    r1309 r1333  
    197197  <p:path style="margin-top: 20px; margin-bottom: 10px;">
    198198    <p:pathelement title="Reggie" href="<%="index.jsp?ID="+ID%>" />
    199     <p:pathelement title="Verify/install required items" />
     199    <p:pathelement title="Installation wizard" />
    200200  </p:path>
    201201
  • extensions/net.sf.basedb.reggie/trunk/resources/persinfo.jsp

    r1326 r1333  
    2626<script language="JavaScript">
    2727
     28var debug = false;
    2829var currentStep = 1;
    2930var pnrIsValid = false;
     
    3132var caseIsValid = false;
    3233var lateralityIsValid = false;
     34var samplingDateIsValid = false;
     35var rnaLaterDateIsValid = false;
    3336
    3437var patientInfo = null;
     
    98101function step3IsValid()
    99102{
    100   return lateralityIsValid;
     103  var isValid = lateralityIsValid;
     104  if (caseInfo.specimen && caseInfo.specimen.length > 0)
     105  {
     106    isValid = isValid && samplingDateIsValid && rnaLaterDateIsValid;
     107  }
     108  return isValid;
    101109}
    102110
     
    279287  frm.pad.value = PAD.replace(/\+/, '-');
    280288  setInputStatus('pad', '', 'valid');
    281 
    282 }
     289}
     290
     291function samplingDateTimeOnChange()
     292{
     293  var frm = document.forms['reggie'];
     294  samplingDateIsValid = false;
     295  setInputStatus('samplingDate', '', '');
     296 
     297  var samplingDate = frm.samplingDate.value;
     298  var samplingTime = frm.samplingTime.value;
     299 
     300  if (samplingDate != '' || samplingTime != '')
     301  {
     302    if (!Dates.isDate(samplingDate, 'yyyy-MM-dd'))
     303    {
     304      setInputStatus('samplingDate', 'Not a valid date', 'invalid');
     305      return;
     306    }
     307    if (frm.rnaLaterDate.value == '') frm.rnaLaterDate.value = samplingDate;
     308   
     309    if (!Dates.isDate(samplingDate + ' ' + samplingTime, 'yyyy-MM-dd HH:mm'))
     310    {
     311      if (samplingDate != '') setInputStatus('samplingDate', 'Not a valid time', 'invalid');
     312      return;
     313    }
     314    setInputStatus('samplingDate', '', 'valid');
     315  }
     316  samplingDateIsValid = true;
     317}
     318
     319function rnaLaterDateTimeOnChange()
     320{
     321  var frm = document.forms['reggie'];
     322  rnaLaterDateIsValid = false;
     323  setInputStatus('rnaLaterDate', '', '');
     324 
     325  var rnaLaterDate = frm.rnaLaterDate.value;
     326  var rnaLaterTime = frm.rnaLaterTime.value;
     327  var rnaLaterTimestamp;
     328 
     329  if (rnaLaterDate != '' || rnaLaterTime != '')
     330  {
     331    if (!Dates.isDate(rnaLaterDate, 'yyyy-MM-dd'))
     332    {
     333      setInputStatus('rnaLaterDate', 'Not a valid date', 'invalid');
     334      return;
     335    }
     336    rnaLaterTimestamp = Dates.parseString(rnaLaterDate + ' ' + rnaLaterTime, 'yyyy-MM-dd HH:mm');
     337    if (rnaLaterTimestamp == null)
     338    {
     339      if (rnaLaterDate != '') setInputStatus('rnaLaterDate', 'Not a valid time', 'invalid');
     340      return;
     341    }
     342    setInputStatus('rnaLaterDate', '', 'valid');
     343  }
     344 
     345  rnaLaterDateIsValid = true;
     346
     347  if (samplingDateIsValid && rnaLaterTimestamp)
     348  {
     349    var samplingTimestamp = Dates.parseString(frm.samplingDate.value + ' ' + frm.samplingTime.value, 'yyyy-MM-dd HH:mm');
     350    if (samplingTimestamp && rnaLaterTimestamp.getDate() != samplingTimestamp.getDate())
     351    {
     352      setInputStatus('rnaLaterDate', 'Sampling and RNA later dates are different', 'warning');
     353    }
     354  }
     355}
     356
    283357
    284358function goNextOnTab(event)
     
    311385  request.send(null);
    312386 
    313   setInnerHTML('debug', request.responseText);
     387  if (debug) Main.debug(request.responseText);
    314388  var response = JSON.parse(request.responseText);
    315389  if (response.status != 'ok')
     
    346420  request.send(null);
    347421 
    348   setInnerHTML('debug', request.responseText);
     422  if (debug) Main.debug(request.responseText);
    349423 
    350424  var response = JSON.parse(request.responseText);
     
    406480  var hasUnknownSpecimen = false;
    407481  var thisCaseLaterality = caseInfo.laterality;
     482  var hasSpecimen = caseInfo.specimen && caseInfo.specimen.length > 0;
    408483  var thisCasePAD = null;
    409484  var hasPAD = false;
    410   if (caseInfo.specimen && caseInfo.specimen.length > 0)
     485  var thisCaseSamplingDate = null;
     486  var thisCaseRNALaterDate = null;
     487 
     488  if (hasSpecimen)
    411489  {
    412490    var specimenTubes = '';
     
    416494      var specimen = caseInfo.specimen[i];
    417495      specimenTubes += specimen.name;
    418       if (specimen.pad)
     496      if (specimen.pad && !hasPAD)
    419497      {
    420498        hasPAD = true;
    421499        thisCasePAD = specimen.pad;
     500      }
     501      if (specimen.samplingDate && !thisCaseSamplingDate)
     502      {
     503        thisCaseSamplingDate = specimen.samplingDate;
     504      }
     505      if (specimen.rnaLaterDate && !thisCaseRNALaterDate)
     506      {
     507        thisCaseRNALaterDate = specimen.rnaLaterDate;
    422508      }
    423509      if (specimen.laterality)
     
    427513        if (specimen.laterality == 'LEFT') hasLeftSpecimen = true;
    428514        if (specimen.laterality == 'RIGHT') hasRightSpecimen = true;
    429         thisCaseLaterality = specimen.laterality;
     515        if (!thisCaseLaterality) thisCaseLaterality = specimen.laterality;
    430516      }
    431517      else
     
    448534      thisCaseLaterality = null;
    449535    }
     536
     537    // Show and populate 'Sampling date' and 'RNA Later date' fields
     538    Main.show('samplingDateSection');
     539    Main.show('rnaLaterDateSection');
     540    if (thisCaseSamplingDate != null)
     541    {
     542      frm.samplingDate.value = thisCaseSamplingDate.substring(0, 10);
     543      frm.samplingTime.value = thisCaseSamplingDate.substring(11, 16);
     544      samplingDateTimeOnChange();
     545    }
     546    if (thisCaseRNALaterDate != null)
     547    {
     548      frm.rnaLaterDate.value = thisCaseRNALaterDate.substring(0, 10);
     549      frm.rnaLaterTime.value = thisCaseRNALaterDate.substring(11, 16);
     550      rnaLaterDateTimeOnChange();
     551    }
     552  }
     553  else
     554  {
     555    // No specimen tubes... if there is only one PAD on the case... use that
     556    if (caseInfo.pad && caseInfo.pad.length == 1)
     557    {
     558      hasPAD = true;
     559      thisCasePAD = caseInfo.pad[0];
     560    }
     561   
     562    // Hide 'Sampling date' and 'RNA Later date' fields
     563    Main.hide('samplingDateSection');
     564    Main.hide('rnaLaterDateSection');
    450565  }
    451566
    452567  frm.pad.value = thisCasePAD;
    453   Main.showHide('padSection', !hasPAD || updateMode);
     568  caseInfo.oldPad = thisCasePAD;
     569  //Main.showHide('padSection', !hasPAD || updateMode);
     570 
     571 
     572 
     573  if (updateMode && !hasSpecimen)
     574  {
     575    // Try to find 'reasonIfNoSpecimen' annotation on the case
     576    for (var i = 0; i < caseInfo.reasonIfNoSpecimen.length; i++)
     577    {
     578      var rns = caseInfo.reasonIfNoSpecimen[i];
     579      if (rns.indexOf('['+caseInfo.originalName+']') == 0)
     580      {
     581        caseInfo.oldReasonIfNoSpecimen = rns;
     582        frm.reasonIfNoSpecimen.value = rns.substring(rns.indexOf(']')+2);
     583        i = 999;
     584      }
     585    }
     586  }
    454587 
    455588  Main.show('caseSection');
     
    561694  }
    562695 
    563   if (!hasPAD && lateralityIsValid) frm.pad.focus();
     696  if (lateralityIsValid) frm.pad.focus();
    564697}
    565698
     
    576709  caseInfo.reasonIfNoSpecimen = frm.reasonIfNoSpecimen.value;
    577710  caseInfo.pad = frm.pad.value;
     711  caseInfo.samplingDate = Main.trimString(frm.samplingDate.value + ' ' + frm.samplingTime.value);
     712  caseInfo.rnaLaterDate = Main.trimString(frm.rnaLaterDate.value + ' ' + frm.rnaLaterTime.value);
    578713
    579714  for (var i = 0; i < frm.laterality.length; i++)
     
    583718  frm.reasonIfNoSpecimen.disabled = true;
    584719  frm.pad.disabled = true;
     720  frm.samplingDate.disabled = true;
     721  frm.samplingTime.disabled = true;
     722  frm.rnaLaterDate.disabled = true;
     723  frm.rnaLaterTime.disabled = true;
    585724
    586725  var updateMode = caseInfo.id;
     
    589728  submitInfo.caseInfo = caseInfo;
    590729
    591   //setInnerHTML('debug', JSON.stringify(submitInfo));
     730  if (debug) Main.debug(JSON.stringify(submitInfo));
    592731 
    593732  var request = Ajax.getXmlHttpRequest();
     
    598737  request.send(JSON.stringify(submitInfo));
    599738
    600   setInnerHTML('debug', request.responseText);
     739  if (debug) Main.debug(request.responseText);
    601740 
    602741  var response = JSON.parse(request.responseText);
     
    715854  font-weight: bold;
    716855  padding: 1px 2px 1px 2px;
     856}
     857
     858.stepfields .subprompt
     859{
     860  width: 150px;
     861  text-align: right;
     862  padding: 1px 2px 1px 2px;
     863  white-space: nowrap;
    717864}
    718865
     
    9301077        <td class="help"><span id="laterality.message" class="message" style="display: none;"></span></td>
    9311078      </tr>
     1079      <tr id="padSection" valign="top">
     1080        <td class="prompt">PAD</td>
     1081        <td class="input"><input type="text" name="pad"
     1082          value="" size="18" maxlength="12"
     1083          onkeypress="focusOnEnter(event, caseInfo.specimen && caseInfo.specimen.length > 0 ? 'samplingDate' : 'reasonIfNoSpecimen')"
     1084          onblur="padOnChange()"></td>
     1085        <td class="status" id="pad.status"></td>
     1086        <td class="help"><span id="pad.message" class="message" style="display: none;"></span></td>
     1087      </tr>
    9321088      <tr valign="top">
    9331089        <td class="prompt">Specimen tubes</td>
     
    9361092        <td class="help"><span id="specimenTubes.message" class="message" style="display: none;"></span>The specimen tube(s) associated with this case.</td>
    9371093      </tr>
    938       <tr id="padSection" valign="top">
    939         <td class="prompt">PAD</td>
    940         <td class="input"><input type="text" name="pad"
    941           value="" size="18" maxlength="12"
    942           onkeypress="focusOnEnter(event, 'reasonIfNoSpecimen')"
    943           onblur="padOnChange()"></td>
    944         <td class="status" id="pad.status"></td>
    945         <td class="help"><span id="pad.message" class="message" style="display: none;"></span>PAD should be entered when no specimen tubes have been registered.</td>
     1094      <tr id="samplingDateSection" valign="top">
     1095        <td class="subprompt">Sampling date</td>
     1096        <td class="input"><input type="text" name="samplingDate" value="" size="12" maxlength="10"
     1097            onkeypress="focusOnEnter(event, 'samplingTime')" onblur="samplingDateTimeOnChange()">
     1098          Time <input type="text" name="samplingTime" value="" size="6" maxlength="5"
     1099            onkeypress="focusOnEnter(event, 'rnaLaterDate')" onblur="samplingDateTimeOnChange()"></td>
     1100        <td class="status" id="samplingDate.status"></td>
     1101        <td class="help"><span id="samplingDate.message" class="message" style="display: none;"></span>Date+time of surgical removal (YYYY-MM-DD, HH:MM)</td>
     1102      </tr>
     1103      <tr id="rnaLaterDateSection" valign="top">
     1104        <td class="subprompt">RNA Later date</td>
     1105        <td class="input"><input type="text" name="rnaLaterDate" value="" size="12" maxlength="10"
     1106            onkeypress="focusOnEnter(event, 'rnaLaterTime')" onblur="rnaLaterDateTimeOnChange()">
     1107          Time <input type="text" name="rnaLaterTime" value="" size="6" maxlength="5"
     1108            onblur="rnaLaterDateTimeOnChange()"></td>
     1109        <td class="status" id="rnaLaterDate.status"></td>
     1110        <td class="help"><span id="rnaLaterDate.message" class="message" style="display: none;"></span>Date+time of pathology handling (YYYY-MM-DD, HH:MM)</td>
    9461111      </tr>
    9471112      <tr id="reasonIfNoSpecimenSection" valign="top">
    948         <td class="prompt">Reason if no specimen</td>
     1113        <td class="subprompt">Reason if no specimen</td>
    9491114        <td class="input"><textarea rows="3" cols="30" name="reasonIfNoSpecimen" value=""></textarea></td>
    9501115        <td class="status"></td>
     
    9721137  </table>
    9731138  </form>
    974 
    975   <pre>
    976   <div id="debug"></div>
    977   </pre>
    9781139 
    9791140</base:body>
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/JsonUtil.java

    r1326 r1333  
    22
    33import java.util.Collection;
     4
     5import net.sf.basedb.reggie.converter.ValueConverter;
    46
    57import org.json.simple.JSONArray;
     
    1618  */
    1719  @SuppressWarnings("unchecked")
    18   public static JSONArray toArray(Collection<?> collection)
     20  public static <F> JSONArray toArray(Collection<F> values, ValueConverter<F, ?> converter)
    1921  {
    2022    JSONArray array = new JSONArray();
    21     if (collection != null)
     23    if (values != null)
    2224    {
    23       array.addAll(collection);
     25      for (F value : values)
     26      {
     27        array.add(converter.convert(value));
     28      }
    2429    }
    2530    return array;
    2631  }
    27  
     32
    2833}
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/Reggie.java

    r1326 r1333  
    11package net.sf.basedb.reggie;
    22
     3import java.util.ArrayList;
    34import java.util.Collections;
    45import java.util.List;
     
    212213  }
    213214   
    214 
    215 
     215  /**
     216    Append an annotation value to a multi-valued annotation type where each
     217    value should be unique.
     218  */
     219  public static void appendAnnotationValueIfUnique(Annotatable item, AnnotationType at, Object value)
     220  {
     221    List<?> currentValues = getAnnotationValues(item, at);
     222    if (!currentValues.contains(value))
     223    {
     224      List<Object> newValues = new ArrayList<Object>(currentValues);
     225      newValues.add(value);
     226      item.getAnnotationSet().getAnnotation(at).setValues(newValues);
     227    }
     228  }
     229
     230  /**
     231    Remove an annotation value to a multi-valued annotation type where each
     232    value should be unique.
     233  */
     234  public static void removeAnnotationValue(Annotatable item, AnnotationType at, Object value)
     235  {
     236    List<?> currentValues = getAnnotationValues(item, at);
     237    if (currentValues.contains(value))
     238    {
     239      List<Object> newValues = new ArrayList<Object>(currentValues);
     240      newValues.remove(value);
     241      item.getAnnotationSet().getAnnotation(at).setValues(newValues);
     242    }
     243  }
     244
     245 
    216246}
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Patient.java

    r1326 r1333  
    33
    44import java.text.SimpleDateFormat;
    5 import java.util.Date;
    65import java.util.List;
    76
     
    1413import net.sf.basedb.core.query.Annotations;
    1514import net.sf.basedb.reggie.Reggie;
     15import net.sf.basedb.reggie.converter.DateToStringConverter;
    1616
    1717/**
     
    9595  public void loadDefaultAnnotations(DbControl dc)
    9696  {
    97     loadAnnotations(dc, "personalNumber", Reggie.ANNOTATION_PERSONAL_NUMBER);
    98     loadAnnotations(dc, "familyName", Reggie.ANNOTATION_FAMILY_NAME);
    99     loadAnnotations(dc, "allFirstNames", Reggie.ANNOTATION_ALL_FIRST_NAMES);
    100     loadAnnotations(dc, "gender", Reggie.ANNOTATION_GENDER);
     97    loadAnnotations(dc, "personalNumber", Reggie.ANNOTATION_PERSONAL_NUMBER, null);
     98    loadAnnotations(dc, "familyName", Reggie.ANNOTATION_FAMILY_NAME, null);
     99    loadAnnotations(dc, "allFirstNames", Reggie.ANNOTATION_ALL_FIRST_NAMES, null);
     100    loadAnnotations(dc, "gender", Reggie.ANNOTATION_GENDER, null);
     101    loadAnnotations(dc, "dateOfBirth", Reggie.ANNOTATION_DATE_OF_BIRTH, new DateToStringConverter(new SimpleDateFormat("yyyy-MM-dd")));
     102    /*
    101103    // Date-of-birth need special handling for formatting
    102104    AnnotationType dateOfBirthType = Reggie.findAnnotationType(dc, Item.BIOSOURCE, Reggie.ANNOTATION_DATE_OF_BIRTH, true);
     
    104106    String dateOfBirth = df.format((Date)Reggie.getAnnotationValue(getBioSource(), dateOfBirthType));
    105107    setAnnotation("dateOfBirth", dateOfBirth);
     108    */
    106109
    107110  }
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/ReggieItem.java

    r1326 r1333  
    99import net.sf.basedb.reggie.JsonUtil;
    1010import net.sf.basedb.reggie.Reggie;
     11import net.sf.basedb.reggie.converter.IdentityConverter;
     12import net.sf.basedb.reggie.converter.ValueConverter;
    1113
    1214
     
    7981  */
    8082  @SuppressWarnings("unchecked")
    81   public void loadAnnotations(String jsonKey, AnnotationType annotationType)
     83  public void loadAnnotations(String jsonKey, AnnotationType annotationType, ValueConverter converter)
    8284  {
     85    if (converter == null) converter = IdentityConverter.INSTANCE;
    8386    JSONObject json = asJSONObject();
    8487    if (annotationType.getMultiplicity() == 1)
    8588    {
    86       json.put(jsonKey, Reggie.getAnnotationValue(item, annotationType));
     89      json.put(jsonKey, converter.convert(Reggie.getAnnotationValue(item, annotationType)));
    8790    }
    8891    else
    8992    {
    90       json.put(jsonKey, JsonUtil.toArray(Reggie.getAnnotationValues(item, annotationType)));
     93      json.put(jsonKey, JsonUtil.toArray(Reggie.getAnnotationValues(item, annotationType), converter));
    9194    }
    9295  }
     
    97100    and then calls {@link #loadAnnotations(String, AnnotationType)}.
    98101  */
    99   public void loadAnnotations(DbControl dc, String jsonKey, String annotationTypeName)
     102  public void loadAnnotations(DbControl dc, String jsonKey, String annotationTypeName, ValueConverter converter)
    100103  {
    101104    AnnotationType annotationType = Reggie.findAnnotationType(dc, item.getType(), annotationTypeName, true);
    102     loadAnnotations(jsonKey, annotationType);
     105    loadAnnotations(jsonKey, annotationType, converter);
    103106  }
    104107 
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/PersonalRegistrationServlet.java

    r1326 r1333  
    33import java.io.IOException;
    44import java.text.SimpleDateFormat;
    5 import java.util.ArrayList;
     5import java.util.Date;
    66import java.util.List;
    77
     
    1515import org.json.simple.parser.JSONParser;
    1616
    17 import net.sf.basedb.core.Annotation;
    1817import net.sf.basedb.core.AnnotationSet;
    1918import net.sf.basedb.core.AnnotationType;
     
    3231import net.sf.basedb.core.query.Restrictions;
    3332import net.sf.basedb.reggie.Reggie;
     33import net.sf.basedb.reggie.converter.DateToStringConverter;
     34import net.sf.basedb.reggie.converter.StringToDateConverter;
    3435import net.sf.basedb.reggie.dao.Case;
    3536import net.sf.basedb.reggie.dao.Patient;
     
    99100          // Continue to load some more info (annotations, etc...)
    100101          // ... case annotations
    101           theCase.loadAnnotations(dc, "laterality", Reggie.ANNOTATION_LATERALITY);
    102           theCase.loadAnnotations(dc, "pad", Reggie.ANNOTATION_PAD_CASE);
    103           theCase.loadAnnotations(dc, "reasonIfNoSpecimen", Reggie.ANNOTATION_REASON_IF_NO_SPECIMEN);
     102          theCase.loadAnnotations(dc, "laterality", Reggie.ANNOTATION_LATERALITY, null);
     103          theCase.loadAnnotations(dc, "pad", Reggie.ANNOTATION_PAD_CASE, null);
     104          theCase.loadAnnotations(dc, "reasonIfNoSpecimen", Reggie.ANNOTATION_REASON_IF_NO_SPECIMEN, null);
    104105         
    105106          // ... patient annotations
     
    124125          AnnotationType padType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD, true);
    125126          AnnotationType lateralityType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_LATERALITY, true);
     127          AnnotationType samplingDateType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_SAMPLING_DATETIME, true);
     128          AnnotationType rnaLaterDateType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_RNALATER_DATETIME, true);
     129          DateToStringConverter dateConverter = new DateToStringConverter(new SimpleDateFormat("yyyy-MM-dd HH:mm"));
    126130          for (SpecimenTube tube : specimenTubes)
    127131          {
    128             tube.loadAnnotations("pad", padType);
    129             tube.loadAnnotations("laterality", lateralityType);
     132            tube.loadAnnotations("pad", padType, null);
     133            tube.loadAnnotations("laterality", lateralityType, null);
     134            tube.loadAnnotations("samplingDate", samplingDateType, dateConverter);
     135            tube.loadAnnotations("rnaLaterDate", rnaLaterDateType, dateConverter);
    130136            jsonTubes.add(tube.asJSONObject());
    131137          }
     
    171177            for (Case c : cases)
    172178            {
    173               c.loadAnnotations("laterality", lateralityType);
     179              c.loadAnnotations("laterality", lateralityType, null);
    174180              jsonCases.add(c.asJSONObject());
    175181            }
     
    313319          // Merge with existing case
    314320          theCase = Sample.getById(dc, caseId);
     321          // Load the real laterality from the case
    315322          laterality = (String)Reggie.getAnnotationValue(theCase, lateralityType);
    316323          jsonMessages.add("Case '" + originalCaseName + "' merged with case '" + theCase.getName() + "' successfully.");
     
    333340        AnnotationSet caseAnnotations = theCase.getAnnotationSet();
    334341        JSONArray jsonSpecimen = (JSONArray)jsonCase.get("specimen");
    335         AnnotationType padType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD, true);
    336342        AnnotationType padCaseType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD_CASE, true);
    337         // Get existing PADcase annotations
    338         List padCase = new ArrayList();
    339         if (caseAnnotations.hasAnnotation(padCaseType))
    340         {
    341           padCase.addAll(caseAnnotations.getAnnotation(padCaseType).getValues());
    342         }
    343         int numOriginalPADCaseValues = padCase.size();
    344343        String pad = Values.getStringOrNull((String)jsonCase.get("pad"));
    345         if (pad != null && !padCase.contains(pad)) padCase.add(pad);
     344        if (pad != null) Reggie.appendAnnotationValueIfUnique(theCase, padCaseType, pad);
    346345        if (jsonSpecimen != null && jsonSpecimen.size() > 0)
    347346        {
     347          AnnotationType padType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD, true);
     348          AnnotationType samplingDateType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_SAMPLING_DATETIME, true);
     349          AnnotationType rnaLaterType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_RNALATER_DATETIME, true);
     350         
     351          StringToDateConverter dateConverter = new StringToDateConverter(new SimpleDateFormat("yyyy-MM-dd HH:mm"));
     352          Date samplingDate = dateConverter.convert((String)jsonCase.get("samplingDate"));
     353          Date rnaLaterDate = dateConverter.convert((String)jsonCase.get("rnaLaterDate"));
     354
    348355          for (int i = 0; i < jsonSpecimen.size(); ++i)
    349356          {
     
    353360            specimen.setPooled(true);
    354361            specimen.getCreationEvent().addSource(theCase, null);
    355             // Copy PAD annotation on specimen to PADcase annotation on case
    356             pad = (String)Reggie.getAnnotationValue(specimen, padType);
    357             if (pad != null && !padCase.contains(pad)) padCase.add(pad);
    358             // Set laterality on the specimen tube if it is missing
    359             if (laterality != null)
    360             {
    361               String specimenLaterality = (String)Reggie.getAnnotationValue(specimen, lateralityType);
    362               if (specimenLaterality == null)
    363               {
    364                 Reggie.setAnnotationValue(specimen, lateralityType, laterality);
    365                 jsonMessages.add("Updated laterality on '" + specimen.getName() + "' to " + laterality + ".");
    366               }
    367             }
    368362           
     363            // Update the specimen annotations
     364            if (laterality != null) Reggie.setAnnotationValue(specimen, lateralityType, laterality);
     365            if (pad != null) Reggie.setAnnotationValue(specimen, padType, pad);
     366            if (samplingDate != null) Reggie.setAnnotationValue(specimen, samplingDateType, samplingDate);
     367            if (rnaLaterDate != null) Reggie.setAnnotationValue(specimen, rnaLaterType, rnaLaterDate);
     368           
    369369          }
    370370          jsonMessages.add(jsonSpecimen.size() + " specimen tube(s) linked with case '" + theCase.getName() + "' successfully.");
     
    373373        {
    374374          AnnotationType reasonIfNoSpecimenType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_REASON_IF_NO_SPECIMEN, true);
    375           Annotation reasonIfNoSpecimen = caseAnnotations.getAnnotation(reasonIfNoSpecimenType);
    376           List values = new ArrayList(reasonIfNoSpecimen.getValues());
    377           values.add("[" + originalCaseName + "] " + jsonCase.get("reasonIfNoSpecimen"));
    378           reasonIfNoSpecimen.setValues(values);
    379         }
    380         if (padCase.size() > numOriginalPADCaseValues)
    381         {
    382           caseAnnotations.getAnnotation(padCaseType).setValues(padCase);
     375          Reggie.appendAnnotationValueIfUnique(theCase, reasonIfNoSpecimenType, "[" + originalCaseName + "] " + jsonCase.get("reasonIfNoSpecimen"));
    383376        }
    384377       
     
    395388        dc = sc.newDbControl();
    396389        Number caseId = (Number)jsonCase.get("id");
    397        
    398390        Sample theCase = Sample.getById(dc, caseId.intValue());
    399        
    400         // Get laterality
     391        String originalCaseName = (String)jsonCase.get("originalName");
     392       
     393        // Get updated case information
    401394        String laterality = Values.getStringOrNull((String)jsonCase.get("laterality"));
    402395        // If the 'laterality' value is a number, then it hasn't changed
    403         if (Values.getInt(laterality) == 0)
    404         {
    405           AnnotationType lateralityType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_LATERALITY, true);
     396        boolean updateLaterality = Values.getInt(laterality, -1) == -1;
     397        String pad = Values.getString((String)jsonCase.get("pad"));
     398        String oldPad = Values.getString((String)jsonCase.get("oldPad"));
     399        JSONArray jsonSpecimen = (JSONArray)jsonCase.get("specimen");
     400     
     401        // Update laterality and PAD for the case
     402        AnnotationType lateralityType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_LATERALITY, true);
     403        AnnotationType padCaseType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD_CASE, true);
     404        if (updateLaterality)
     405        {
    406406          Reggie.setAnnotationValue(theCase, lateralityType, laterality);
    407           int numSpecimen = 0;
    408           for (Sample specimen : theCase.getChildSamples().list(dc))
    409           {
    410             Reggie.setAnnotationValue(specimen, lateralityType, laterality);
    411             numSpecimen++;
    412           }
    413           jsonMessages.add("Updated case '" + theCase.getName() + "' and " +numSpecimen +
    414               " specimen tube(s) to laterality="+laterality);
    415         }
    416 
     407        }
     408        if (pad != null)
     409        {
     410          if (oldPad != null) Reggie.removeAnnotationValue(theCase, padCaseType, oldPad);
     411          Reggie.appendAnnotationValueIfUnique(theCase, padCaseType, pad);
     412        }
     413        jsonMessages.add("Case '" + originalCaseName + "' updated successfully.");
     414       
     415        // Update the specimen tubes
     416        if (jsonSpecimen != null && jsonSpecimen.size() > 0)
     417        {
     418          AnnotationType padType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_PAD, true);
     419          AnnotationType samplingDateType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_SAMPLING_DATETIME, true);
     420          AnnotationType rnaLaterType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_RNALATER_DATETIME, true);
     421         
     422          StringToDateConverter dateConverter = new StringToDateConverter(new SimpleDateFormat("yyyy-MM-dd HH:mm"));
     423          Date samplingDate = dateConverter.convert((String)jsonCase.get("samplingDate"));
     424          Date rnaLaterDate = dateConverter.convert((String)jsonCase.get("rnaLaterDate"));
     425         
     426          for (int i = 0; i < jsonSpecimen.size(); ++i)
     427          {
     428            JSONObject jsonSpec = (JSONObject)jsonSpecimen.get(i);
     429            Sample specimen = Sample.getById(dc, ((Number)jsonSpec.get("id")).intValue());
     430           
     431            // Update the specimen annotations
     432            if (updateLaterality) Reggie.setAnnotationValue(specimen, lateralityType, laterality);
     433            if (pad != null) Reggie.setAnnotationValue(specimen, padType, pad);
     434            if (samplingDate != null) Reggie.setAnnotationValue(specimen, samplingDateType, samplingDate);
     435            if (rnaLaterDate != null) Reggie.setAnnotationValue(specimen, rnaLaterType, rnaLaterDate);
     436           
     437          }
     438          jsonMessages.add(jsonSpecimen.size() + " specimen tube(s) updated.");
     439
     440        }
     441        else
     442        {
     443          // No specimen tubes...update the 'reasonIfNoSpecimen' annotation
     444          AnnotationType reasonIfNoSpecimenType = Reggie.findAnnotationType(dc, Item.SAMPLE, Reggie.ANNOTATION_REASON_IF_NO_SPECIMEN, true);
     445         
     446          String rns = Values.getString((String)jsonCase.get("reasonIfNoSpecimen"));
     447          String oldRns = Values.getString((String)jsonCase.get("oldReasonIfNoSpecimen"));
     448          if (oldRns != null)
     449          {
     450            Reggie.removeAnnotationValue(theCase, reasonIfNoSpecimenType, oldRns);
     451          }
     452          if (rns != null)
     453          {
     454            Reggie.appendAnnotationValueIfUnique(theCase, reasonIfNoSpecimenType, "[" + originalCaseName + "] " + rns);
     455          }
     456         
     457        }
     458       
    417459        dc.commit();
    418460        json.put("messages", jsonMessages);
Note: See TracChangeset for help on using the changeset viewer.