Changeset 6510


Ignore:
Timestamp:
Dec 3, 2021, 9:24:38 AM (8 months ago)
Author:
Nicklas Nordborg
Message:

Merge Reggie 4.33.5 to the trunk

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
3 deleted
42 edited
3 copied

Legend:

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

  • extensions/net.sf.basedb.reggie/trunk/META-INF/servlets.xml

    r6179 r6510  
    186186  </servlet>
    187187  <servlet>
    188     <servlet-name>FutureSpecimen</servlet-name>
    189     <servlet-class>net.sf.basedb.reggie.servlet.FutureSpecimenServlet</servlet-class>
     188    <servlet-name>ExternalSpecimen</servlet-name>
     189    <servlet-class>net.sf.basedb.reggie.servlet.ExternalSpecimenServlet</servlet-class>
    190190  </servlet>
    191191  <servlet>
  • extensions/net.sf.basedb.reggie/trunk/resources/batch/import-external-specimen.js

    r6474 r6510  
    2929
    3030    Wizard.showLoadingAnimation('Loading items...');
    31     var url = '../FutureSpecimen.servlet?ID='+App.getSessionId();
     31    var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId();
    3232    url += '&cmd=GetImportInformation';
    3333    Wizard.asyncJsonRequest(url, specimen.initializeStep1);
     
    5151   
    5252    html += '<tr>';
    53     html += '<th>Type</th>';
    5453    html += '<th class="dottedleft">Item</th>';
     54    html += '<th class="dottedleft">Case</th>';
    5555    html += '<th class="dottedleft">JSON file</th>'
    5656    html += '<th>Date</th>';
     
    7878
    7979      html += '<tr class="highlight ' + (itemNo % 4 < 2 ? 'evenrow' : 'oddrow') + '">';
    80       html += '<td>'+(Strings.encodeTags(item.itemType) || '-')+'</td>';
    81       html += '<td class="dottedleft">'+(Strings.encodeTags(item.name) || '-')+'</td>';
     80      html += '<td class="dottedleft">';
     81      if (item.name)
     82      {
     83        html += Strings.encodeTags(item.name);
     84        if (item.itemType) html += ' <span class="itemsubtype">('+Strings.encodeTags(item.itemType)+')</span>';
     85      }
     86      else
     87      {
     88        html += '-';
     89      }
     90      html += '<td class="dottedleft">';
     91      if (item.currentCase)
     92      {
     93        html += Strings.encodeTags(item.currentCase.name);
     94        html += '<img src="../images/case_summary.png" class="link case-summary" data-name="'+Strings.encodeTags(item.currentCase.name)+'" title="Show case summary (popup window)">';
     95      }
     96      else
     97      {
     98        html += '-';
     99      }
     100      html += '</td>';
    82101      html += '<td class="dottedleft" style="white-space: nowrap;">';
    83102      if (jsonFile)
     
    137156      if (jsonFile && jsonFile.warnings)
    138157      {
    139         html += '<div class="messagecontainer note"><ol start="'+startNo+'">';
     158        var moreWarnings = jsonFile.warnings.length > 6;
     159        html += '<div class="messagecontainer note '+(moreWarnings?'minimal':'')+'" id="warnings.'+itemNo+'"><ol start="'+startNo+'">';
    140160        for (var warnNo = 0; warnNo < jsonFile.warnings.length; warnNo++)
    141161        {
     
    144164        html += '</ol></div>';
    145165        startNo += jsonFile.warnings.length;
     166        if (moreWarnings)
     167        {
     168          html += '<div class="morewarnings">'+jsonFile.warnings.length+' warnings - <span class="showmore-warnings link" data-item-no="'+itemNo+'">Show more...</span></div>';
     169        }
    146170      }
    147171      if (canImport && startNo == 1)
     
    163187    }
    164188
    165    
     189    var showMoreWarnings = document.getElementsByClassName('showmore-warnings');
     190    for (var itemNo = 0; itemNo < showMoreWarnings.length; itemNo++)
     191    {
     192      Events.addEventHandler(showMoreWarnings[itemNo], 'click', specimen.toggleWarnings);
     193    }
     194 
     195    var cs = document.getElementsByClassName('case-summary');
     196    for (var i = 0; i < cs.length; i++)
     197    {
     198      Events.addEventHandler(cs[i], 'click', Reggie.openCaseSummaryPopupOnEvent);
     199    }
     200
    166201    Doc.show('step-1');
    167202    Doc.show('gonext');
    168203  }
     204 
     205  specimen.toggleWarnings = function(event)
     206  {
     207    var itemNo = Data.get(event.currentTarget, 'item-no');
     208    var warningsDiv = Doc.element('warnings.'+itemNo);
     209    Doc.addOrRemoveClass(warningsDiv, 'minimal');
     210    event.currentTarget.innerHTML = warningsDiv.classList.contains('minimal') ? 'Show more...' : 'Show less...';
     211  }
    169212
    170213  specimen.downloadJsonFile = function(event)
     
    173216    var file = importItems[itemNo].jsonFile;
    174217
    175     var url = '../FutureSpecimen.servlet?ID='+App.getSessionId();
     218    var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId();
    176219    url += '&cmd=DownloadJsonFile';
    177220    url += '&file='+encodeURIComponent(file.name);
     
    296339
    297340  /**
    298     Sort by file date of JSON files. Items without a file (eg. FutureSpecimen)
    299     are sorted last by name.
     341    Sort by file date of JSON files. Items without a file are sorted last by name.
    300342  */
    301343  specimen.sortByFileDate = function(a, b)
     
    359401    }
    360402
    361     var url = '../FutureSpecimen.servlet?ID='+App.getSessionId();
     403    var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId();
    362404    url += '&cmd=ImportFromJSON';
    363405   
  • extensions/net.sf.basedb.reggie/trunk/resources/batch/import-external-specimen.jsp

    r6350 r6510  
    8080  opacity: 0.5;
    8181}
     82
     83.messagecontainer.minimal
     84{
     85  max-height: 5.5em;
     86  overflow: auto;
     87}
     88
     89.morewarnings
     90{
     91  font-weight: bold;
     92  font-style: italic;
     93  font-size: 90%;
     94  margin-left: 1em;
     95  margin-bottom: 0.25em;
     96}
     97.morewarnings:before
     98{
     99  content: '►';
     100}
     101
     102img.case-summary
     103{
     104  margin-left: 0.25em;
     105}
    82106</style>
    83107</base:head>
  • extensions/net.sf.basedb.reggie/trunk/resources/index.jsp

    r6442 r6510  
    10801080              <li><span class="require-permission" data-role="PatientCurator" data-link="personal/persinfo.jsp?ID=<%=ID%>"
    10811081                >Pathology referral form registration</span>
     1082                <span class="counter more" data-counter="specimen-local-without-case"
     1083                  title="Number of (local) specimen tubes not linked to a case">∙</span><span
     1084                  class="counter" data-counter="specimen-external-without-case"
     1085                  title="Number of (external) specimen tubes not linked to a case">∙</span>
    10821086 
    10831087              <li><span class="require-permission" data-role="PatientCurator" data-link="personal/bloodform.jsp?ID=<%=ID%>"
     
    11351139              <li><span class="require-permission" data-role="Administrator" data-link="batch/import-external-specimen.jsp?ID=<%=ID%>"
    11361140                >Import externally processed samples</span>
    1137                 <span class="counter more" data-counter="future-specimen"
    1138                   title="Number of FutureSpecimen items waiting for information">∙</span><span
    1139                   class="counter" data-counter="import-files"
     1141                <span class="counter" data-counter="import-files"
    11401142                  title="Number JSON files waiting to be imported">∙</span>
    11411143             
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/bloodform.js

    r6277 r6510  
    1010
    1111  var caseIsValid = false;
     12  var pnrIsTested = false;
    1213  var pnrIsValid = false;
    1314  var pnrIsAcceptable = false;
     
    9899      frm.personalNumber.value = patientInfo.personalNumber;
    99100      blood.personalNumberOnChange();
     101      pnrIsValid = true;
    100102      Wizard.goNext(false);
    101103    }
     
    107109    var frm = document.forms['reggie'];
    108110    var pnr = frm.personalNumber.value;
     111   
    109112    pnrIsValid = false;
     113    pnrIsAcceptable = false;
     114    pnrIsTested = true;
     115   
     116    var pnrLen = pnr.length;
     117    if (pnrLen == 0)
     118    {
     119      Wizard.setInputStatus('personalNumber', 'invalid', 'A personal number is required');
     120      return;
     121    }
     122   
    110123    pnrIsAcceptable = true;
    111      
    112     var pnrLen = pnr.length;
    113124    if (pnrLen != 12 && pnrLen != 10)
    114125    {
     
    158169  blood.validateStep1 = function(event)
    159170  {
    160     if (event.detail.auto)
    161     {
    162       if (!caseIsValid || !pnrIsValid)
    163       {
    164         if (pnrIsAcceptable)
    165         {
    166           var frm = document.forms['reggie'];
    167           frm.personalNumber.focus();
    168           Wizard.showGoNextConfirmation(true, 'Check to verify registration of non-standard personal number.');
    169         }
     171    if (!pnrIsTested) persinfo.personalNumberOnChange();
     172    if (!caseIsValid || !pnrIsValid)
     173    {
     174      if (!pnrIsAcceptable)
     175      {
    170176        event.preventDefault();
    171       }
    172     }
    173     else
    174     {
    175       if (!caseIsValid || !pnrIsAcceptable) event.preventDefault();
     177        return;
     178      }
     179      var frm = document.forms['reggie'];
     180      if (!frm.verifyGoNext)
     181      {
     182        frm.personalNumber.focus();
     183        Wizard.showGoNextConfirmation(true, 'Check to verify registration of non-standard personal number.');
     184        event.preventDefault();
     185      }
    176186    }
    177187  }
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/persinfo.js

    r6239 r6510  
    88  var bloodInfo = null;
    99
     10  var pnrIsTested = false;
    1011  var pnrIsValid = false;
    1112  var pnrIsAcceptable = false;
     
    2627    Events.addEventHandler('personalNumber', 'keyup', persinfo.personalNumberOnChange);
    2728    Events.addEventHandler('personalNumber', 'keypress', Wizard.goNextOnTabOrEnter);
     29    Events.addEventHandler('select-waiting-case', 'click', persinfo.showCaseSelection);
     30    Events.addEventHandler('select-case', 'click', persinfo.caseSelected);
     31    Events.addEventHandler(document.body, 'click', persinfo.hideCaseSelection);
    2832   
    2933    // Step 2
     
    3842    Events.addEventHandler('step-3', 'wizard-validate', persinfo.validateStep3);
    3943    Events.addEventHandler('pad', 'blur', persinfo.padOnChange);
    40     Events.addEventHandler('newNoSpecimen', 'click', persinfo.newSpecimenTypeOnChange);
    41     Events.addEventHandler('newFutureSpecimen', 'click', persinfo.newSpecimenTypeOnChange);
    4244    Events.addEventHandler('samplingDate', 'blur', persinfo.samplingDateTimeOnChange);
    4345    Events.addEventHandler('samplingTime', 'blur', persinfo.samplingDateTimeOnChange);
     
    6062    Doc.show('step-1');
    6163    Doc.show('gonext');
    62   }
     64   
     65    var url = '../PersonalRegistration.servlet?ID='+App.getSessionId();
     66    url += '&cmd=GetSpecimenWithoutCase';
     67    Wizard.showLoadingAnimation('Loading information about specimen tubes...');
     68    Wizard.asyncJsonRequest(url, persinfo.onSpecimenTubesLoaded);
     69  }
     70 
     71  persinfo.onSpecimenTubesLoaded = function(response)
     72  {
     73    var specimenTubes = response.specimenTubes;
     74    if (specimenTubes.length == 0) return;
     75   
     76    var html = '';
     77    var lastPrefix = null;
     78    for (var spNo = 0; spNo < specimenTubes.length; spNo++)
     79    {
     80      var sp = specimenTubes[spNo];
     81      var prefix = sp.name.substr(0, 2);
     82      if (lastPrefix && prefix != lastPrefix)
     83      {
     84        html += '<div class="menuseparator"></div>';
     85      }
     86      lastPrefix = prefix;
     87      html += '<div class="menuitem interactable enabled" id="sp-'+sp.id+'" data-case-name="'+Strings.encodeTags(sp.name)+'">';
     88      html += Strings.encodeTags(sp.name);
     89      if (sp.numSpecimen > 1) html += ' ('+sp.numSpecimen+')';
     90      if (sp.externalRef) html += ' – '+Strings.encodeTags(sp.externalRef);
     91      html += '</div>';
     92    }
     93    Doc.element('select-case-all').innerHTML = html;
     94    Doc.element('num-waiting-cases').innerHTML = specimenTubes.length+(specimenTubes.length == 1 ? ' case':' cases')+' waiting for registration';
     95    Doc.show('waitingCasesSection');
     96  }
     97 
     98  persinfo.showCaseSelection = function(event)
     99  {
     100    var menu = Doc.element('select-case');
     101    menu.style.display = 'block';
     102    var x = event.clientX+1;
     103    var y = event.clientY;
     104    menu.style.left = (x)+'px';
     105    menu.style.top = (y)+'px';
     106    event.stopPropagation();
     107  }
     108 
     109  persinfo.hideCaseSelection = function()
     110  {
     111    Doc.hide('select-case');
     112  }
     113 
     114  persinfo.caseSelected = function(event)
     115  {
     116    var frm = document.forms['reggie'];
     117    var name = Data.get(event.target, 'case-name');
     118    frm.caseName.value = name;
     119    frm.personalNumber.focus();
     120    persinfo.caseNameOnChange();
     121  }
     122
    63123 
    64124  persinfo.caseNameOnChange = function()
     
    67127    var caseName = frm.caseName.value.toUpperCase();
    68128    caseIsValid = false;
     129    Doc.element('numSpecimenTubes').innerHTML = '';
    69130    if (caseName == '')
    70131    {
     
    97158    caseInfo = response.caseInfo;
    98159    bloodInfo = response.bloodInfo;
     160    var numSpecimenTubes = caseInfo.specimen ? caseInfo.specimen.length : 0;
     161    Doc.element('numSpecimenTubes').innerHTML = '<i>('+(numSpecimenTubes || 'no')+' existing specimen '+(numSpecimenTubes==1?'item':'items')+')</i>';
    99162   
    100163    if (caseInfo && caseInfo.patient)
     
    102165      frm.personalNumber.value = caseInfo.patient.personalNumber;
    103166      persinfo.personalNumberOnChange();
     167      pnrIsValid = true;
    104168      Wizard.goNext(false);
    105169    }
     
    108172      frm.personalNumber.value = bloodInfo.patient.personalNumber;
    109173      persinfo.personalNumberOnChange();
     174      pnrIsValid = true;
    110175      Wizard.goNext(false);
    111176    }
     
    117182    var pnr = frm.personalNumber.value;
    118183    pnrIsValid = false;
     184    pnrIsAcceptable = false;
     185    pnrIsTested = true;
     186   
     187    var pnrLen = pnr.length;
     188    if (pnrLen == 0)
     189    {
     190      Wizard.setInputStatus('personalNumber', 'invalid', 'A personal number is required');
     191      return;
     192    }
     193   
    119194    pnrIsAcceptable = true;
    120    
    121     var pnrLen = pnr.length;
    122195    if (pnrLen != 12 && pnrLen != 10)
    123196    {
     
    167240  persinfo.validateStep1 = function(event)
    168241  {
    169     if (event.detail.auto)
    170     {
    171       if (!caseIsValid || !pnrIsValid)
    172       {
    173         if (pnrIsAcceptable)
    174         {
    175           var frm = document.forms['reggie'];
    176           frm.personalNumber.focus();
    177           Wizard.showGoNextConfirmation(true, 'Check to verify registration of non-standard personal number.');
    178         }
     242    if (!pnrIsTested) persinfo.personalNumberOnChange();
     243    if (!caseIsValid || !pnrIsValid)
     244    {
     245      if (!pnrIsAcceptable)
     246      {
    179247        event.preventDefault();
    180       }
    181     }
    182     else
    183     {
    184       if (!caseIsValid || !pnrIsAcceptable) event.preventDefault();
     248        return;
     249      }
     250      var frm = document.forms['reggie'];
     251      if (!frm.verifyGoNext)
     252      {
     253        frm.personalNumber.focus();
     254        Wizard.showGoNextConfirmation(true, 'Check to verify registration of non-standard personal number.');
     255        event.preventDefault();
     256      }
    185257    }
    186258  }
     
    332404    if (hasSpecimen)
    333405    {
    334       var specimenTubes = '<table class="specimen-table">';
    335       specimenTubes += '<tr>';
    336       specimenTubes += '<th class="id-col">ID</th>';
    337       specimenTubes += '<th class="laterality-col">Laterality</th>';
    338       specimenTubes += '<th class="yellow-col">Yellow</th>';
    339       specimenTubes += '</tr>';
    340      
    341       Doc.hide('reasonIfNoSpecimenSection');
    342       Doc.hide('otherPathNoteSection');
     406      Doc.element('specimenTubes').innerHTML = persinfo.createSpecimenHtml();
     407     
    343408      for (var i = 0; i < caseInfo.specimen.length; i++)
    344409      {
    345410        var specimen = caseInfo.specimen[i];
    346411        var isYellow = specimen.YellowLabel != null;
    347         var isPaused = specimen.bioWell.bioPlate.name.indexOf('PSp') == 0;
    348412        specimen.YellowLabelOriginal = specimen.YellowLabel;
    349         specimenTubes += '<tr id="specimen-row.'+specimen.id+'" class="specimen-tube'+(isYellow?' yellow':'')+(isPaused?' paused':'')+'">';
    350         specimenTubes += '<td class="id-col">'+Strings.encodeTags(specimen.name)+'</td>';
    351         specimenTubes += '<td class="laterality-col">';
     413 
     414        frm['yellow.'+specimen.id].checked = isYellow;
     415        Forms.selectListOption(frm['specimenType.'+specimen.id], specimen.specimenType);
     416        Forms.selectListOption(frm['biopsyType.'+specimen.id], specimen.biopsyType);
     417        frm['comment.'+specimen.id].value = specimen.operatorDeliveryComment;
     418        frm['otherPathNote.'+specimen.id].value = specimen.otherPathNote;
     419        Events.addEventHandler('yellow.'+specimen.id, 'click', persinfo.yellowOnChange);
     420
    352421        if (specimen.pad && !hasPAD)
    353422        {
     
    365434        if (specimen.laterality)
    366435        {
    367           specimenTubes += Strings.encodeTags(specimen.laterality);
    368436          Forms.checkRadio(frm.laterality, specimen.laterality);
    369437          if (specimen.laterality == 'LEFT') hasLeftSpecimen = true;
     
    374442        {
    375443          hasUnknownSpecimen = true;
    376           specimenTubes += '<i>unknown</i>';
    377         }
    378         specimenTubes += '</td>';
    379         specimenTubes += '<td class="yellow-col">';
    380         specimenTubes += '<input type="checkbox" name="yellow.'+specimen.id+'" id="yellow.'+specimen.id+'"';
    381         specimenTubes += (isYellow? 'checked' : '');
    382         specimenTubes += ' data-specimen-id="'+specimen.id+'" data-index="'+i+'"';
    383         specimenTubes += '></td>';
    384         specimenTubes += '</tr>';
    385       }
    386       specimenTubes += '</table>';
    387       Doc.element('specimenTubes').innerHTML = specimenTubes;
    388      
    389       for (var i = 0; i < caseInfo.specimen.length; i++)
    390       {
    391         var specimen = caseInfo.specimen[i];
    392         Events.addEventHandler('yellow.'+specimen.id, 'click', persinfo.yellowOnChange);
     444        }
    393445      }
    394446     
     
    400452      if (numLateralities > 1)
    401453      {
    402         Wizard.setInputStatus('specimenTubes', 'warning', 'Specimen tubes with different laterality');
     454        Wizard.setInputStatus('laterality', 'warning', 'Specimen tubes with different laterality');
    403455        thisCaseLaterality = null;
    404456      }
     
    406458      Doc.show('samplingDateSection');
    407459      Doc.show('rnaLaterDateSection');
    408 
     460      Doc.show('specimenTubes');
    409461    }
    410462    else
     
    416468        thisCaseSamplingDate = caseInfo.noSpecimen.samplingDate;
    417469        frm.reasonIfNoSpecimen.value = caseInfo.noSpecimen.reasonIfNoSpecimen;
    418        
    419         Doc.element('specimenTubes').innerHTML = '<i>not found -- NoSpecimen item already exists and can be updated</i>';
    420         persinfo.displaySpecimenTypeForm('NO_SPECIMEN');
    421         Doc.element('newFutureSpecimen').disabled = true;
    422         Forms.checkRadio(frm.newSpecimenType, 'NO_SPECIMEN');
     470        Doc.element('noSpecimenTubes').innerHTML = '<i>not found -- NoSpecimen item already exists and can be updated</i>';
     471        Doc.show('noSpecimenSection');
    423472        Doc.element('existingItemName').innerHTML = Strings.encodeTags(caseInfo.noSpecimen.name);
    424473        Doc.show('existingItemNameSection');
    425474      }
    426       else if (caseInfo.futureSpecimen)
    427       {
    428         thisCasePAD = caseInfo.futureSpecimen.pad;
    429         thisCaseSamplingDate = caseInfo.futureSpecimen.samplingDate;
    430         thisCaseRNALaterDate = caseInfo.futureSpecimen.rnaLaterDate;
    431         frm.otherPathNote.value = caseInfo.futureSpecimen.otherPathNote;
    432         Doc.element('specimenTubes').innerHTML = '<i>not found -- FutureSpecimen item already exists and can be updated</i>';
    433         persinfo.displaySpecimenTypeForm('FUTURE_SPECIMEN');
    434         Doc.element('newNoSpecimen').disabled = true;
    435         Forms.checkRadio(frm.newSpecimenType, 'FUTURE_SPECIMEN');
    436         Doc.element('existingItemName').innerHTML = Strings.encodeTags(caseInfo.futureSpecimen.name);
    437         Doc.show('existingItemNameSection');
    438       }
    439475      else
    440476      {
    441         Doc.element('specimenTubes').innerHTML = '<i>not found -- NoSpecimen or FutureSpecimen item will be created</i>';
    442         Doc.show('selectSpecimenTypeSection');
    443         persinfo.displaySpecimenTypeForm(frm.newSpecimenType.value);
    444         Doc.show('selectSpecimenTypeSection');
    445       }
     477        Doc.element('noSpecimenTubes').innerHTML = '<i>not found -- NoSpecimen item will be created</i>';
     478        Doc.show('noSpecimenSection');
     479      }
     480      Doc.show('samplingDateSection');
     481      Doc.hide('samplingTimeField');
     482      frm.samplingTime.disabled = true;
     483      Doc.show('reasonIfNoSpecimenSection');
    446484    }
    447485
     
    524562        if (!updateMode || cc.id == caseInfo.id)
    525563        {
    526           cases += '<label><input type="radio" name="laterality" value="' + cc.id + '" id="laterality'+cc.id+'"';
     564          cases += '<label><input type="radio" name="laterality" value="' + (cc.laterality || cc.id) + '" id="laterality'+cc.id+'"';
    527565          if (cc.laterality == thisCaseLaterality) cases += ' checked';
    528566          cases += '>';
     
    627665  }
    628666 
    629   persinfo.newSpecimenTypeOnChange = function(event)
    630   {
    631     var frm = document.forms['reggie'];
    632     persinfo.displaySpecimenTypeForm(frm.newSpecimenType.value);
    633     frm.samplingDate.focus();
    634   }
    635  
    636   persinfo.displaySpecimenTypeForm = function(specimenType)
    637   {
    638     var frm = document.forms['reggie'];
    639    
    640     if (specimenType == 'NO_SPECIMEN')
    641     {
    642       Doc.hide('samplingTimeField');
    643       frm.samplingTime.disabled = true;
    644       Doc.hide('rnaLaterDateSection');
    645       Doc.show('reasonIfNoSpecimenSection');
    646       Doc.hide('otherPathNoteSection');
    647     }
    648     else if (specimenType == 'FUTURE_SPECIMEN')
    649     {
    650       Doc.show('samplingTimeField', 'inline');
    651       frm.samplingTime.disabled = false;
    652       Doc.show('rnaLaterDateSection');
    653       Doc.hide('reasonIfNoSpecimenSection');
    654       Doc.show('otherPathNoteSection');
    655     }
     667  persinfo.createSpecimenHtml = function()
     668  {
     669    var html = '';
     670    for (var i = 0; i < caseInfo.specimen.length; i++)
     671    {
     672      var specimen = caseInfo.specimen[i];
     673      var isYellow = specimen.YellowLabel != null;
     674      var isPaused = specimen.bioWell && specimen.bioWell.bioPlate.name.indexOf('PSp') == 0;
     675      specimen.YellowLabelOriginal = specimen.YellowLabel;
     676
     677      html += '<tr class="section-header">';
     678      html += '<td colspan="4">Specimen Tube '+Strings.encodeTags(specimen.name)+'</td>';
     679      html += '</tr>';
     680     
     681      html += '<tr>';
     682      html += '<td class="subprompt">Laterality</td>';
     683      html += '<td class="input">'+Strings.encodeTags(specimen.laterality || 'unknown')+'</td>';
     684      html += '<td class="status" id="laterality.'+specimen.id+'.status"></td>';
     685      html += '<td class="help"><span id="laterality.'+specimen.id+'.message" class="message"></span></td>';   
     686      html += '</tr>';
     687
     688      html += '<tr id="specimen-row.'+specimen.id+'" class="specimen-tube'+(isYellow?' yellow':'')+(isPaused?' paused':'')+'">';
     689      html += '<td class="subprompt yellow-tag"><label for="yellow.'+specimen.id+'">Yellow label</label></td>';
     690      html += '<td class="input">';
     691      html += '<input type="checkbox" name="yellow.'+specimen.id+'" id="yellow.'+specimen.id+'"';
     692      html += ' data-specimen-id="'+specimen.id+'"';
     693      html += '></td>';
     694      html += '<td class="status"></td>';
     695      html += '<td class="help"></td>';   
     696      html += '</tr>';
     697
     698      html += '<tr>'
     699      html += '<td class="subprompt">Biopsy type</td>';
     700      html += '<td class="input">';
     701      html += '<select name="biopsyType.'+specimen.id+'" id="biopsyType.'+specimen.id+'">';
     702      html += '<option selected value="">unknown';
     703      html += '<option value="SpecimenSurgery">SpecimenSurgery';
     704      html += '<option value="SpecimenCoreBiopsy">SpecimenCoreBiopsy';
     705      html += '<option value="SpecimenCoreBiopsy2nd">SpecimenCoreBiopsy2nd';
     706      html += '<option value="SpecimenFineNeedleAspiration">SpecimenFineNeedleAspiration';
     707      html += '</select>';
     708      html += '</td>';
     709      html += '<td class="status" id="biopsyType.'+specimen.id+'.status"></td>';
     710      html += '<td class="help"><span id="biopsyType.'+specimen.id+'.message" class="message"></span></td>';   
     711      html += '</tr>';
     712
     713     
     714      html += '<tr>'
     715      html += '<td class="subprompt">Specimen type</td>';
     716      html += '<td class="input">';
     717      html += '<select name="specimenType.'+specimen.id+'" id="specimenType.'+specimen.id+'">';
     718      html += '<option selected value="">unknown';
     719      html += '<option value="Primary">Primary';
     720      html += '<option value="LymphnodeRegional">LymphnodeRegional';       
     721      html += '<option value="MetastasisDistant">MetastasisDistant';
     722      html += '<option value="RecurrenceLocal">RecurrenceLocal';
     723      html += '<option value="RecurrenceRegional">RecurrenceRegional';
     724      html += '<option value="Normal">Normal';
     725      html += '<option value="Uncertain">Uncertain';
     726      html += '</select>';
     727      html += '</td>';
     728      html += '<td class="status" id="specimenType.'+specimen.id+'.status"></td>';
     729      html += '<td class="help"><span id="specimenType.'+specimen.id+'.message" class="message"></span></td>';   
     730      html += '</tr>';
     731
     732      html += '<tr class="align-top">';
     733      html += '<td class="subprompt">Other path note</td>';
     734      html += '<td class="input"><textarea rows="3" name="otherPathNote.'+specimen.id+'" id="otherPathNote.'+specimen.id+'"></textarea></td>';
     735      html += '<td class="status" id="otherPathNote.'+specimen.id+'.status"></td>';
     736      html += '<td class="help"><span id="otherPathNote.'+specimen.id+'.message" class="message"></span>In this field, enter ALL text noted on the referral form by the pathologist.</td>';   
     737      html += '</tr>';
     738     
     739      html += '<tr class="align-top">';
     740      html += '<td class="subprompt">Operator delivery comment</td>';
     741      html += '<td class="input"><textarea rows="3" name="comment.'+specimen.id+'" id="comment.'+specimen.id+'"></textarea></td>';
     742      html += '<td class="status" id="comment.'+specimen.id+'.status"></td>';
     743      html += '<td class="help"><span id="comment.'+specimen.id+'.message" class="message"></span>In this field, enter information specific for the specimen tube.</td>';   
     744      html += '</tr>';
     745    }
     746    return html;
    656747  }
    657748 
     
    669760  {
    670761    var spId = Data.get(event.currentTarget, 'specimen-id');
    671     var index = Data.get(event.currentTarget, 'index');
    672762    Doc.addOrRemoveClass('specimen-row.'+spId, 'yellow', event.currentTarget.checked);
    673     caseInfo.specimen[index].YellowLabel = event.currentTarget.checked ? 'yellow' : null;
    674763  }
    675764 
     
    9161005
    9171006    caseInfo.laterality = Forms.getCheckedRadio(frm.laterality).value;
    918     caseInfo.newSpecimenType = frm.newSpecimenType.value;
    9191007    caseInfo.reasonIfNoSpecimen = frm.reasonIfNoSpecimen.value;
    920     caseInfo.otherPathNote = frm.otherPathNote.value;
    9211008    caseInfo.pad = frm.pad.value;
    9221009   
     
    9411028    {
    9421029      caseInfo.copyConsent = parseInt(frm.copyConsent.value, 10);
     1030    }
     1031
     1032    if (caseInfo.specimen && caseInfo.specimen.length > 0)
     1033    {
     1034      for (var i = 0; i < caseInfo.specimen.length; i++)
     1035      {
     1036        var specimen = caseInfo.specimen[i];
     1037        specimen.YellowLabel = frm['yellow.'+specimen.id].checked ? 'yellow' : null;
     1038        specimen.specimenType = frm['specimenType.'+specimen.id].value;
     1039        specimen.biopsyType = frm['biopsyType.'+specimen.id].value;
     1040        specimen.otherPathNote = frm['otherPathNote.'+specimen.id].value;
     1041        specimen.operatorDeliveryComment = frm['comment.'+specimen.id].value;
     1042      }
    9431043    }
    9441044
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/persinfo.jsp

    r6349 r6510  
    3030>
    3131<style>
    32 .specimen-table
    33 {
    34   width: 22em;
    35 }
    36 .specimen-table td, .specimen-table th
    37 {
    38   padding: 2px;
    39 }
    40 .specimen-table tr
    41 {
    42   border-bottom-width: 1px;
    43 }
    44 .yellow
     32.yellow td:not(.help)
    4533{
    4634  background-color: #FFFFC0;
    47 }
    48 .id-col, .laterality-col
    49 {
    50   text-align: left;
    51 }
    52 .yellow-col
    53 {
    54   text-align: center;
    55 }
    56 .paused .yellow-col
    57 {
    58     background-image: url('../images/pause.png');
    59     background-repeat: no-repeat;
    60     background-position: 100% 50%;
    6135}
    6236</style>
     
    6640  <p:path><p:pathelement
    6741    title="Reggie" href="<%="../index.jsp?ID="+ID%>"
    68     /><p:pathelement title="Personal information registration"
     42    /><p:pathelement title="Pathology referral form registration"
    6943    /></p:path>
    7044
     
    7953   
    8054      <table class="step-form">
     55      <tr id="waitingCasesSection" style="display: none;">
     56        <td class="subprompt"><span id="num-waiting-cases"></span></td>
     57        <td class="input">
     58          <span id="select-waiting-case" class="link">Select<img src="../images/marked.png" style="vertical-align: baseline; margin-left: 2px;">
     59          </span>
     60          <div id="select-case" class="menu vertical bg-filled-100"
     61            style="z-index: 2; display: none; width: 20em; min-height: 12em; max-height: 25em; overflow: auto;">
     62            <div id="select-case-all"></div>
     63          </div>
     64        </td>
     65        <td class="status"></td>
     66        <td class="help"></td>
     67      </tr>
    8168      <tr>
    8269        <td class="prompt">Case name</td>
     
    8572            class="required auto-init" data-auto-init="focus" data-next-focus="personalNumber"
    8673            style="width: 12em;" maxlength="12">
     74          <span id="numSpecimenTubes"></span>
    8775        </td>
    8876        <td class="status" id="caseName.status"></td>
     
    214202        </td>
    215203      </tr>
    216       <tr>
     204      <tr id="noSpecimenSection" style="display: none;">
    217205        <td class="prompt">Specimen tubes</td>
    218         <td class="input" id="specimenTubes"><i>not found</i></td>
    219         <td class="status" id="specimenTubes.status"></td>
    220         <td class="help">
    221           <span id="specimenTubes.message" class="message"></span>
    222           The specimen tube(s) associated with this case.
    223         </td>
    224       </tr>
    225       <tr id="selectSpecimenTypeSection" style="display: none;">
    226         <td class="subprompt"></td>
    227         <td class="input" colspan="2" style="padding-top: 4px; padding-bottom: 4px; background-color: #f0f080;">
    228           <label><input type="radio" name="newSpecimenType" id="newNoSpecimen" value="NO_SPECIMEN" checked>NoSpecimen</label>
    229           <label><input type="radio" name="newSpecimenType" id="newFutureSpecimen" value="FUTURE_SPECIMEN" disabled>FutureSpecimen (not yet supported)</label>
    230         </td>
    231         <td class="help">
    232           Select if a NoSpecimen item or a FutureSpecimen item should be registered for this case.
    233         </td>
     206        <td class="input" id="noSpecimenTubes"></td>
     207        <td class="status"></td>
     208        <td class="help"></td>
    234209      </tr>
    235210      <tr id="existingItemNameSection" style="display: none;">
     
    239214        <td class="help"></td>
    240215      </tr>
    241       <tr id="samplingDateSection">
     216      <tr id="samplingDateSection" style="display: none;">
    242217        <td class="subprompt">Sampling date</td>
    243218        <td class="input">
     
    253228        </td>
    254229      </tr>
    255       <tr id="rnaLaterDateSection">
     230      <tr id="rnaLaterDateSection" style="display: none;">
    256231        <td class="subprompt">RNA Later date</td>
    257232        <td class="input">
     
    268243        </td>
    269244      </tr>
    270       <tr id="reasonIfNoSpecimenSection" class="align-top">
     245      <tr id="reasonIfNoSpecimenSection" class="align-top" style="display: none;">
    271246        <td class="subprompt">Reason if no specimen</td>
    272247        <td class="input">
     
    277252        <td class="help">Comment why there was no specimen tubes in the delivery.</td>
    278253      </tr>
    279       <tr id="otherPathNoteSection" class="align-top">
    280         <td class="subprompt">Other path note</td>
    281         <td class="input">
    282           <textarea name="otherPathNote" id="otherPathNote" rows="4"></textarea>
    283         </td>
    284         <td class="status"></td>
    285         <td class="help">In this field, enter ALL text noted on the referral form by the pathologist.</td>
    286       </tr>
     254      <tbody id="specimenTubes" style="display: none;"></tbody>
    287255      </table>
    288256    </div>
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/retraction_followup_form.js

    r6159 r6510  
    249249    var html = '';
    250250    html += rf.tableRowsForItems('Specimen', response.specimen, 'SAMPLE');
    251     html += rf.tableRowsForItems('FutureSpecimen', response.futureSpecimen, 'SAMPLE', true);
    252251    html += rf.tableRowsForItems('Lysate', response.lysate, 'EXTRACT');
    253252    html += rf.tableRowsForItems('RNA', response.rna, 'EXTRACT');
     
    273272      }
    274273     
    275       if (response.futureSpecimen)
    276       {
    277         Wizard.setInputStatus('itemList', 'warning', 'FutureSpecimen exists! We need to wait for more information from the external lab.');
    278       }
    279274    }
    280275    else
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/retractionform.js

    r6155 r6510  
    385385    var specimen = response.specimen;
    386386    var noSpecimen = response.noSpecimen;
    387     var futureSpecimen = response.futureSpecimen;
    388387    var histology = response.histology;
    389388    var stained = response.stained;
     
    433432    }
    434433    if (noSpecimen && noSpecimen.length > 0)
    435     {
    436       itemExists = true;
    437     }
    438     if (futureSpecimen && futureSpecimen.length > 0)
    439434    {
    440435      itemExists = true;
     
    513508      html += htmlTableRowsForItems(specimen, 'Specimen', 'specimen', 'Sampling', 'PAD', 'Storage box', false, false);
    514509      html += htmlTableRowsForItems(noSpecimen, 'NoSpecimen', 'nospecimen', 'Sampling', 'PAD', 'NA', false, false);
    515       html += htmlTableRowsForItems(futureSpecimen, 'FutureSpecimen', 'futurespecimen', 'Sampling', 'PAD', 'NA', false, false);
    516510      html += htmlTableRowsForItems(histology, 'Histology', 'histology', 'Partition', null, 'Paraffin block', true, true);
    517511      html += htmlTableRowsForItems(stained, 'Stained', 'stained', null, null, 'Slide', false, false);
  • extensions/net.sf.basedb.reggie/trunk/resources/reports/case-summary.js

    r6479 r6510  
    203203    var specimen = response.specimen;
    204204    var noSpecimen = response.noSpecimen;
    205     var futureSpecimen = response.futureSpecimen;
    206205    var numSpecimenOfAnyType = 0;
    207206    var yellowPrefixes = {};
     
    266265      defaultColClass = null;
    267266    }
    268     if (futureSpecimen && futureSpecimen.length > 0)
    269     {
    270       futureSpecimen.sort(cs.sortByIdDescending);
    271       var truncateAt = TRUNCATE_SIZE[Math.min(futureSpecimen.length-1, TRUNCATE_SIZE.length)];
    272       maxItemsInLeftCol = Math.max(maxItemsInLeftCol, futureSpecimen.length);
    273       for (var i = 0; i < futureSpecimen.length; i++)
    274       {
    275         try
    276         {
    277           var s = futureSpecimen[i];
    278           cs.addColumn('futurespecimen.name', cs.asLink('SAMPLE', s, 0, true));
    279           cs.addColumn('futurespecimen.donotuse', cs.asDoNotUse(s));
    280           cs.addColumn('futurespecimen.registrationDate', cs.asDate(s.registrationDate));
    281           cs.addColumn('futurespecimen.laterality', cs.warnIfMissing(Strings.encodeTags(s.laterality)));
    282           cs.addColumn('futurespecimen.samplingDate', cs.warnIfMissing(cs.asDateTime(s.samplingDate)));
    283           cs.addColumn('futurespecimen.rnaLaterDate', cs.warnIfMissing(cs.asDateTime(s.rnaLaterDate, s.samplingDate)));
    284           cs.addColumn('futurespecimen.pad', cs.warnIfMissing(Strings.encodeTags(s.pad)));
    285           cs.addColumn('futurespecimen.biopsyType', s.biopsyType);
    286           cs.addColumn('futurespecimen.comment', cs.truncate(s.comment, truncateAt));
    287           numSpecimenOfAnyType++;
    288         }
    289         catch (e)
    290         {
    291           cs.logError('specimen-info', e);
    292         }
    293       }
    294       defaultColClass = null;
    295     }
    296267   
    297268    if (numSpecimenOfAnyType == 0)
     
    300271      Doc.hide('specimen-details');
    301272      Doc.hide('nospecimen-info');
    302       Doc.hide('futurespecimen-info');
    303273    }
    304274    else
     
    310280      }
    311281      if (!noSpecimen || noSpecimen.length == 0) Doc.hide('nospecimen-info');
    312       if (!futureSpecimen || futureSpecimen.length == 0) Doc.hide('futurespecimen-info');
    313282    }
    314283   
  • extensions/net.sf.basedb.reggie/trunk/resources/reports/case_summary.jsp

    r6479 r6510  
    326326        </div>
    327327       
    328         <div class="info-section bg-filled-100" id="futurespecimen-info">
    329           <div>
    330           <table class="info-table">
    331           <thead>
    332             <tr id="futurespecimen.name">
    333               <th id="futurespecimen-header">Future specimen</th>
    334             </tr>
    335           </thead>
    336           <tbody id="futurespecimen-details" class="info-details">
    337             <tr id="futurespecimen.donotuse" class="dynamic-column">
    338               <th>DoNotUse</th>
    339             </tr>
    340             <tr id="futurespecimen.registrationDate">
    341               <th>Registration date</th>
    342             </tr>
    343             <tr id="futurespecimen.laterality">
    344               <th>Laterality</th>
    345             </tr>
    346             <tr id="futurespecimen.samplingDate">
    347               <th>Sampling date</th>
    348             </tr>
    349             <tr id="futurespecimen.rnaLaterDate">
    350               <th>RNA later date</th>
    351             </tr>
    352             <tr id="futurespecimen.pad" class="confidential">
    353               <th>PAD</th>
    354             </tr>
    355             <tr id="futurespecimen.biopsyType">
    356               <th>Biopsy type</th>
    357             </tr>
    358             <tr id="futurespecimen.comment" class="comment dynamic-column">
    359               <th>Comment</th>
    360             </tr>
    361           </tbody>
    362           </table>
    363           </div>
    364         </div>
    365        
    366328        <div class="info-section bg-filled-100" id="histology-info">
    367329          <div>
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/counter/CounterService.java

    r6387 r6510  
    416416    json.put("specimen-all", query.count(dc));
    417417   
     418    // Specimen tubes not linked to a Case
     419    query = Sample.getQuery();
     420    Subtype.SPECIMEN.addFilter(dc, query);
     421    query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     422    query.restrict(Restrictions.eq(Hql.property("parent"), null));
     423    // Filter on externalId to get rid of external samples that never get a parent item
     424    query.restrict(Restrictions.like(Hql.property("externalId"), Expressions.string(Subtype.SPECIMEN.getExternalIdPrefix()+"%")));
     425    query.setCacheResult(true);
     426    long specimenAllWithNoCase = query.count(dc);
     427   
     428    // Specimen tubes not linked to a Case that have an ExternalRef annotation
     429    query = Sample.getQuery();
     430    Subtype.SPECIMEN.addFilter(dc, query);
     431    query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     432    query.restrict(Restrictions.eq(Hql.property("parent"), null));
     433    // Filter on externalId to get rid of external samples that never get a parent item
     434    query.restrict(Restrictions.like(Hql.property("externalId"), Expressions.string(Subtype.SPECIMEN.getExternalIdPrefix()+"%")));
     435    // ExternaRef not null
     436    query.join(Annotations.innerJoin(null, Annotationtype.EXTERNAL_REF.load(dc), "eref"));
     437    query.setCacheResult(true);
     438    long specimenExternalWithNoCase = query.count(dc);
     439    json.put("specimen-local-without-case", specimenAllWithNoCase - specimenExternalWithNoCase);
     440    json.put("specimen-external-without-case", specimenExternalWithNoCase);
     441   
    418442    // Specimen tubes to be partitioned
    419443    query = Sample.getQuery();
     
    488512    query.setCacheResult(true);
    489513    json.put("case-or-blood-without-consent", query.count(dc));
    490    
    491     // FutureSpecimen
    492     query = Sample.getQuery();
    493     Subtype.FUTURE_SPECIMEN.addFilter(dc, query);
    494     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
    495     query.setCacheResult(true);
    496     json.put("future-specimen", query.count(dc));
    497514  }
    498515 
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Annotationtype.java

    r6476 r6510  
    588588
    589589  /**
    590     The "QiacubeRunNo" annotation type, used for extracts (RNA, DNA).
     590    The "QiacubeRunNo" annotation type, used for extracts (RNA, DNA, FlowThrough).
    591591    It is an integer annotation type with allowed values >= 1.
    592592    @since 2.6
     
    595595    new Annotationtype("QiacubeRunNo", Type.INT, false, Item.EXTRACT);
    596596
     597  /**
     598    The "QiacubeRunId" annotation type, used for extracts (RNA, DNA, FlowThrough)
     599    extract by external lab. It is a string ID-like annotation
     600    that group items that has been extracted in the same Qiacube run.
     601    @since 4.33.5
     602  */
     603  public static final Annotationtype QIACUBE_RUN_ID =
     604    new Annotationtype("QiacubeRunId", Type.STRING, false, Item.EXTRACT);
     605
     606 
    597607  /**
    598608    The "RLT_Plus" annotation type, used for extracts (Lysate).
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Case.java

    r6193 r6510  
    6767    {
    6868      // Not found... see if we can find a different case
    69       // with 'Specimen'/'NoSpecimen'/'FutureSpecimen' child items belonging to this case (merged case)
     69      // with 'Specimen'/'NoSpecimen' child items belonging to this case (merged case)
    7070      merged = true;
    7171      caseQuery = Sample.getQuery();
     
    7575      caseQuery.join(Hql.innerJoin("evt", "bioMaterial", "sp")); // 'sp' should now reference a specimen tube
    7676     
    77       // Restrict to 'Specimen', 'NoSpecimen' or 'FutureSpecimen' child items
    78       caseQuery.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, "sp"), Subtype.NO_SPECIMEN.restriction(dc, "sp"), Subtype.FUTURE_SPECIMEN.restriction(dc, "sp")));
     77      // Restrict to 'Specimen' or 'NoSpecimen' or 'FutureSpecimen' child items
     78      caseQuery.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, "sp"), Subtype.NO_SPECIMEN.restriction(dc, "sp")));
    7979      caseQuery.restrict(Restrictions.like(Hql.property("sp", "name"), Expressions.parameter("name", name + ".%", Type.STRING)));
    8080      caseQuery.setDistinct(true);
     
    162162  /**
    163163    Get a list with all case numbers associated with a patient. This method look
    164     for all sample of type {@link Subtype#SPECIMEN}, {@link Subtype#NO_SPECIMEN},
    165     {@link Subtype#FUTURE_SPECIMEN} and {@link Subtype#BLOOD} for the given patient.
     164    for all sample of type {@link Subtype#SPECIMEN}, {@link Subtype#NO_SPECIMEN}
     165    and {@link Subtype#BLOOD} for the given patient.
    166166    The case numbers are returned as strings sorted in numerical order.
    167167    @since 2.12
     
    179179   
    180180    query = Sample.getQuery();
    181     query.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, null), Subtype.NO_SPECIMEN.restriction(dc, null), Subtype.FUTURE_SPECIMEN.restriction(dc, null)));
     181    query.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, null), Subtype.NO_SPECIMEN.restriction(dc, null)));
    182182    query.restrict(Restrictions.eq(Hql.property("parent.parent"), Hql.entity(patient.getBioSource())));
    183183    for (Sample spec : query.list(dc))
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/SpecimenTube.java

    r6193 r6510  
    272272    query.restrict(Restrictions.or(
    273273        Subtype.SPECIMEN.restriction(dc, null),
    274         Subtype.NO_SPECIMEN.restriction(dc, null),
    275         Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     274        Subtype.NO_SPECIMEN.restriction(dc, null)
    276275        ));
    277276    query.restrict(Restrictions.like(Hql.property("name"), Expressions.string(caseName + ".%")));
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Subtype.java

    r6477 r6510  
    9292  public static final Subtype NO_SPECIMEN = new Subtype("NoSpecimen", null, null, "S", Item.SAMPLE, false);
    9393
    94   /**
    95     The definition of the "FutureSpecimen" subtype (for cases when a specimen is expected but has not yet
    96     been received).
    97     @since 4.32
    98   */
    99   public static final Subtype FUTURE_SPECIMEN = new Subtype("FutureSpecimen", null, null, "S", Item.SAMPLE, false);
    100 
    101  
    10294  /**
    10395    The definition of the "TMASpecimen" subtype.
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/DateValidator.java

    r6343 r6510  
    102102  {
    103103    Date result = null;
    104     try
     104    if (value != null)
    105105    {
    106       result = dateFormat.parse(value);
    107     }
    108     catch (Exception ex)
    109     {
    110       section.addErrorMessage("Invalid date in JSON: "+entryKey+"="+value+" (expected format: "+format+")");
    111     }
    112     if (result != null)
    113     {
    114       if (notAfter != null && result.after(notAfter))
     106      try
    115107      {
    116         section.addWarningMessage("Future date in JSON: "+entryKey+"="+value+" (parsed as '"+result+"'");
     108        result = dateFormat.parse(value);
    117109      }
    118       if (notBefore != null && result.before(notBefore))
     110      catch (Exception ex)
    119111      {
    120         section.addWarningMessage("Old date in JSON: "+entryKey+"="+value+
    121           " (expected after "+dateFormat.format(notBefore)+")");
     112        section.addErrorMessage("Invalid date in JSON: "+entryKey+"="+value+" (expected format: "+format+")");
     113      }
     114      if (result != null)
     115      {
     116        if (notAfter != null && result.after(notAfter))
     117        {
     118          section.addWarningMessage("Future date in JSON: "+entryKey+"="+value+" (parsed as '"+result+"'");
     119        }
     120        if (notBefore != null && result.before(notBefore))
     121        {
     122          section.addWarningMessage("Old date in JSON: "+entryKey+"="+value+
     123            " (expected after "+dateFormat.format(notBefore)+")");
     124        }
    122125      }
    123126    }
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/DnaInfo.java

    r6344 r6510  
    1919  public Integer qiacubePos;
    2020  public Integer qiacubeRunNumber;
     21  public String qiacubeRunId;
    2122  public String operator;
    2223  public Float qubitConc;
     
    2526  public boolean valid;
    2627 
    27   public DnaInfo(JsonSection section)
     28  public DnaInfo(JsonSection section, RnaInfo rna)
    2829  {
    2930    if (section != null)
     
    3435      operator = section.getOptionalEntry("Qiacube operator", null);
    3536     
    36       // TODO - qiacube run number
    37       // TODO -- concentrations and quantities
     37      qiacubeRunId = section.getRequiredEntry("Qiacube run number", PatternValidator.CMD_ID);
     38      if (rna != null)
     39      {
     40        if (qiacubeRunId != null && !qiacubeRunId.equals(rna.qiacubeRunId))
     41        {
     42          section.addErrorMessage("DNA/Qiacube run doesn't match RNA/Qiacube run: "+qiacubeRunId + "<>"+rna.qiacubeRunId);
     43        }
     44        else if (qiacubePos != null && !qiacubePos.equals(rna.qiacubePos))
     45        {
     46          section.addErrorMessage("DNA/Qiacube position doesn't match RNA/Qiacube position: "+qiacubePos + "<>"+rna.qiacubePos);
     47        }
     48        qiacubeRunNumber = rna.qiacubeRunNumber;
     49      }
     50     
    3851      qubitConc = section.getRequiredEntry("Concentration (ng/ul)", FloatValidator.POSITIVE);
    39       // TODO -- protocol
    4052      protocol = section.getRequiredEntry("Protocol", ProtocolValidator.EXTRACTION_PROTOCOL);
     53     
     54      // TODO -- implementation is needed
     55      section.getOptionalEntry("Box and position", NullValidator.warnIfNull(String.class));
     56      section.getOptionalEntry("Original quantity", NullValidator.warnIfNull(Number.class));
     57      section.getOptionalEntry("DNA ID", NullValidator.warnIfNull(String.class));
    4158    }
    4259    valid = section != null && !section.hasError();
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FastqInfo.java

    r6474 r6510  
    3838      {
    3939        //R1.md5 = fastq.getOptionalEntry("R1 MD5", PatternValidator.MD5);
    40         R1.expectedSize = fastq.getOptionalEntry("R1size", LongValidator.POSITIVE_OR_NULL);
     40        R1.expectedSize = fastq.getOptionalEntry("R1size", NullValidator.allowNull(LongValidator.POSITIVE));
    4141      }
    4242      if (R2 != null)
    4343      {
    4444        //R2.md5 = fastq.getOptionalEntry("R2 MD5", PatternValidator.MD5);
    45         R2.expectedSize = fastq.getOptionalEntry("R2size", LongValidator.POSITIVE_OR_NULL);
     45        R2.expectedSize = fastq.getOptionalEntry("R2size", NullValidator.allowNull(LongValidator.POSITIVE));
    4646      }
    4747    }
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FloatValidator.java

    r6205 r6510  
    2222  public static final FloatValidator POSITIVE = new FloatValidator(0f, null);
    2323
     24  /**
     25    Validator for RIN values that should be between 0 and 10.
     26    @since 4.33.5
     27  */
     28  public static final FloatValidator RIN = new FloatValidator(0f, 10f);
     29 
    2430  private Float maxValue;
    2531  private Float minValue;
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FlowThroughInfo.java

    r6221 r6510  
    1919  public Integer qiacubePos;
    2020  public Integer qiacubeRunNumber;
     21  public String qiacubeRunId;
    2122  public String operator;
    2223
     
    2425  public boolean valid;
    2526 
    26   public FlowThroughInfo(JsonSection section)
     27  public FlowThroughInfo(JsonSection section, RnaInfo rna)
    2728  {
    2829    if (section != null)
     
    3334      operator = section.getOptionalEntry("Qiacube operator", null);
    3435     
    35       // TODO - qiacube run number
    36       // TODO -- concentrations and quantities
    37       // TODO -- protocol
     36      if (rna != null)
     37      {
     38        if (qiacubeRunId != null && !qiacubeRunId.equals(rna.qiacubeRunId))
     39        {
     40          section.addErrorMessage("FlowThrough/Qiacube run doesn't match RNA/Qiacube run: "+qiacubeRunId + "<>"+rna.qiacubeRunId);
     41        }
     42        else if (qiacubePos != null && !qiacubePos.equals(rna.qiacubePos))
     43        {
     44          section.addErrorMessage("FlowThrough/Qiacube position doesn't match RNA/Qiacube position: "+qiacubePos + "<>"+rna.qiacubePos);
     45        }
     46        qiacubeRunNumber = rna.qiacubeRunNumber;
     47      }
     48     
    3849      protocol = section.getRequiredEntry("Protocol", ProtocolValidator.EXTRACTION_PROTOCOL);
     50     
     51      // TODO -- implementation is needed
     52      section.getOptionalEntry("Box and position", NullValidator.warnIfNull(String.class));
     53      section.getOptionalEntry("Original quantity", NullValidator.warnIfNull(Number.class));
     54      section.getOptionalEntry("FlowThrough ID", NullValidator.warnIfNull(String.class));
    3955    }
    4056    valid = section != null && !section.hasError();
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/JsonFile.java

    r6474 r6510  
    277277        specimenInfo = new SpecimenInfo(getRequiredSection("Specimen"), mainInfo);
    278278        lysateInfo = new LysateInfo(getRequiredSection("Lysate"), specimenInfo);
    279         dnaInfo = new DnaInfo(getRequiredSection("DNA"));
    280         rnaInfo = new RnaInfo(getRequiredSection("RNA"));
    281         flowThroughInfo = new FlowThroughInfo(getRequiredSection("FlowThrough"));
     279        rnaInfo = new RnaInfo(getRequiredSection("RNA"), ctx);
     280        dnaInfo = new DnaInfo(getRequiredSection("DNA"), rnaInfo);
     281        flowThroughInfo = new FlowThroughInfo(getRequiredSection("FlowThrough"), rnaInfo);
    282282      }
    283       libInfo = new LibraryInfo(getRequiredSection("Library"), ctx);
     283      libInfo = new LibraryInfo(getRequiredSection("Library"), mainInfo, ctx);
    284284      poolInfo = new PoolInfo(getRequiredSection("Pool"), libInfo, ctx);
    285285      flowCellInfo = new FlowCellInfo(getRequiredSection("FlowCell"), poolInfo);
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/JsonSection.java

    r6457 r6510  
    8989    Get an optional entry from the JSON file. A validator is
    9090    optional, but if a validator is given it will be called
    91     also for null values (but not if the entry is missing).
     91    also for null values or if the entry is missing.
    9292  */
    9393  @SuppressWarnings("unchecked")
     
    9595  {
    9696    T result = null;
    97     if (json.containsKey(key))
     97    Object val = json.get(key);
     98    if (validator != null)
    9899    {
    99       Object val = json.get(key);
    100       if (validator != null)
     100      if (val != null && !validator.getExpectedClass().isInstance(val))
    101101      {
    102         if (val != null && !validator.getExpectedClass().isInstance(val))
    103         {
    104           addErrorMessage("Invalid entry in JSON: "+section+"."+key+"="+val+
    105             " (expected "+validator.getExpectedClass().getSimpleName()+", got " + val.getClass().getSimpleName()+")");
    106         }
    107         else
    108         {
    109           try
    110           {
    111             result = validator.isValid(file.dc(), (F)val, this, section+"."+key);
    112           }
    113           catch (Exception ex)
    114           {
    115             addErrorMessage("Invalid entry in JSON: "+section+"."+key+"="+val+" ("+ex.getMessage()+")");
    116           }
    117         }
     102        addErrorMessage("Invalid entry in JSON: "+section+"."+key+"="+val+
     103          " (expected "+validator.getExpectedClass().getSimpleName()+", got " + val.getClass().getSimpleName()+")");
    118104      }
    119105      else
    120106      {
    121         result = (T)val;
     107        try
     108        {
     109          result = validator.isValid(file.dc(), (F)val, this, section+"."+key);
     110        }
     111        catch (Exception ex)
     112        {
     113          addErrorMessage("Invalid entry in JSON: "+section+"."+key+"="+val+" ("+ex.getMessage()+")");
     114        }
    122115      }
     116    }
     117    else
     118    {
     119      result = (T)val;
    123120    }
    124121    return result;
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LibraryInfo.java

    r6474 r6510  
    2222import net.sf.basedb.reggie.dao.Pipeline;
    2323import net.sf.basedb.reggie.dao.Subtype;
     24import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef.SampleIdType;
    2425import net.sf.basedb.util.Coordinate;
    2526
     
    5152  public boolean valid;
    5253 
    53   public LibraryInfo(JsonSection section, ImportContext ctx)
     54  public LibraryInfo(JsonSection section, MainInfo main, ImportContext ctx)
    5455  {
    5556    if (section != null)
     
    8990      barcode = section.getRequiredEntry("Barcode", BarcodeValidator.INSTANCE);
    9091      protocol = section.getRequiredEntry("Protocol", ProtocolValidator.LIB_PROTOCOL);
     92     
     93      // TODO -- implementation is needed
     94      SampleIdType idType = main.idRef != null ? main.idRef.idType : null;
     95      if (idType != SampleIdType.PRENORMALISED_RNA)
     96      {
     97        section.getOptionalEntry("Used quantity", NullValidator.warnIfNull(Number.class));
     98      }
    9199    }
    92100    valid = section != null && !section.hasError();
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LongValidator.java

    r6474 r6510  
    1717    Allow all long values.
    1818  */
    19   public static final LongValidator ALL = new LongValidator(false);
    20  
    21   /**
    22     All all long and null values.
    23     @since 4.33.4
    24   */
    25   public static final LongValidator ALL_OR_NULL = new LongValidator(true);
     19  public static final LongValidator ALL = new LongValidator();
    2620 
    2721  /**
    2822    All positive values > 0.
    2923  */
    30   public static final LongValidator POSITIVE = new LongValidator(1l, null, false);
     24  public static final LongValidator POSITIVE = new LongValidator(1l, null);
    3125
    32   /**
    33     All positive values > 0 or null.
    34     @since 4.33.4
    35   */
    36   public static final LongValidator POSITIVE_OR_NULL = new LongValidator(1l, null, true);
    37  
    38   private boolean allowNull;
    3926  private Long maxValue;
    4027  private Long minValue;
     
    4633    Allow all long values.
    4734  */
    48   public LongValidator(boolean allowNull)
    49   {
    50     this.allowNull = allowNull;
    51   }
     35  public LongValidator()
     36  {}
    5237 
    5338  /**
     
    5540    Null values are allowed and mean no limit.
    5641  */
    57   public LongValidator(Long min, Long max, boolean allowNull)
     42  public LongValidator(Long min, Long max)
    5843  {
    5944    this.minValue = min;
    6045    this.maxValue = max;
    61     this.allowNull = allowNull;
    6246  }
    6347 
     
    10185  {
    10286    Long result = null;
    103     if (value == null)
    104     {
    105       if (!allowNull)
    106       {
    107         section.addErrorMessage("Missing long in JSON: "+entryKey);
    108       }
    109     }
    110     else if (value instanceof Number)
     87    if (value instanceof Number)
    11188    {
    11289      result = ((Number)value).longValue();
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LysateInfo.java

    r6221 r6510  
    3232      originalVolume = section.getRequiredEntry("Original volume (ul)", FloatValidator.POSITIVE);
    3333      usedFromSpecimen = section.getRequiredEntry("Used quantity (mg)", FloatValidator.POSITIVE);
    34       // TODO -- protocol
    3534      protocol = section.getRequiredEntry("Protocol", ProtocolValidator.SAMPLE_HANDLING_PROTOCOL);
     35     
     36      // TODO -- implementation is needed
     37      section.getOptionalEntry("Multiple pieces", NullValidator.warnIfNull(Number.class));
     38      section.getOptionalEntry("Box and position", NullValidator.warnIfNull(String.class));
     39      section.getOptionalEntry("Remaining volume", NullValidator.warnIfNull(Number.class));
     40      section.getOptionalEntry("Lysate ID", NullValidator.warnIfNull(String.class));
    3641     
    3742      if (specimen.originalQuantity != null && specimen.remainingQuantity != null && usedFromSpecimen != null)
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/PatternValidator.java

    r6221 r6510  
    1818{
    1919  /**
    20     A CMD ID is expected to be string with numbers and hyphen.
     20    A CMD ID is expected to be string with numbers and hyphen. We
     21    add 'cmd:' prefix to the value.
    2122  */
    2223  public static final PatternValidator CMD_ID = new PatternValidator("[0-9]+[0-9\\-]+", "ID", "cmd:$0", null);
    2324
     25  /**
     26    A CMD Protocol. We allow any text, but add 'cmd:' prefix.
     27  */
     28  public static final PatternValidator CMD_PROTOCOL = new PatternValidator(".+", "ID", "cmd:$0", null);
     29 
     30  /**
     31    A Clarity ID is expected to be string with numbers and letters.
     32  */
     33  public static final PatternValidator CLARITY_ID = new PatternValidator("[A-Z0-9]++", "Clarity ID", "cmd:$0", null);
     34 
    2435  /**
    2536    A flow cell ID is uppercase letters and numbers. Typically
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/PlateWellValidator.java

    r6474 r6510  
    2424    Validator for plates with 8 rows and 12 columns.
    2525  */
    26   public static final PlateWellValidator PLATE_8x12 = new PlateWellValidator(8, 12);
     26  public static final PlateWellValidator PLATE_8x12 = new PlateWellValidator(8, 12, CoordinateSystem.ALPHA_NUMERIC);
    2727 
    2828  /**
     
    3030    @since 4.33.4
    3131  */
    32   public static final PlateWellValidator STRIP_1x8 = new PlateWellValidator(1, 8);
     32  public static final PlateWellValidator STRIP_1x8 = new PlateWellValidator(1, 8, CoordinateSystem.NUMERIC);
    3333 
    3434  /**
    3535    Validator fow Qiacube positions which are represented as 6 rows with 2 columns.
    3636  */
    37   public static final PlateWellValidator QIACUBE = new PlateWellValidator(6, 2);
     37  public static final PlateWellValidator QIACUBE = new PlateWellValidator(6, 2, CoordinateSystem.NUMERIC_ALPHA);
    3838
    39   private final Pattern a1b1Pattern;
    40   private final Pattern numericPattern;
    4139  private final int maxRows;
    4240  private final int maxCols;
     41  private final CoordinateSystem[] systems;
    4342 
    44   public PlateWellValidator(int maxRows, int maxCols)
     43  public PlateWellValidator(int maxRows, int maxCols, CoordinateSystem... systems)
    4544  {
    46     this.a1b1Pattern = Pattern.compile("([A-Z]+)\\:(\\d+)");
    47     this.numericPattern = Pattern.compile("(\\d+)\\:(\\d+)");
    4845    this.maxRows = maxRows;
    4946    this.maxCols = maxCols;
     47    this.systems = systems;
    5048  }
    5149 
     
    5351  public PlateCoordinate isValid(DbControl dc, String value, JsonSection section, String entryKey)
    5452  {
    55     Matcher mA1B1 = a1b1Pattern.matcher(value);
    56     int row;
    57     int col;
    58     boolean useA1B1;
    59     if (!mA1B1.matches())
     53   
     54    for (CoordinateSystem cs : systems)
    6055    {
    61       Matcher mNumeric = numericPattern.matcher(value);
    62       if (!mNumeric.matches())
     56      Matcher m = cs.matcher(value);
     57      if (m.matches())
    6358      {
    64         section.addErrorMessage("Invalid plate well in JSON: "+entryKey+"="+value);
    65         return null;
     59        int row = cs.getRow(m);
     60        int col = cs.getCol(m);
     61        boolean valid = true;
     62       
     63        if (row < 1)
     64        {
     65          section.addErrorMessage("Row coordinate <"+cs.row(1)+" in JSON: "+entryKey+"="+value);
     66          valid = false;
     67        }
     68        else if (row > maxRows)
     69        {
     70          section.addErrorMessage("Row coordinate >"+cs.row(maxRows)+" in JSON: "+entryKey+"="+value);
     71          valid = false;
     72        }
     73        if (col < 1)
     74        {
     75          section.addErrorMessage("Column coordinate <"+cs.col(1)+" in JSON: "+entryKey+"="+value);
     76          valid = false;
     77        }
     78        else if (col > maxCols)
     79        {
     80          section.addErrorMessage("Column coordinate >"+cs.col(maxCols)+" in JSON: "+entryKey+"="+value);
     81          valid = false;
     82        }
     83       
     84        return valid ? new PlateCoordinate(row-1, col-1) : null;
    6685      }
    67       row = Integer.parseInt(mNumeric.group(1));
    68       col = Integer.parseInt(mNumeric.group(2));
    69       useA1B1 = false;
    70     }
    71     else
    72     {
    73       row = Coordinate.alphaToNumeric(mA1B1.group(1));
    74       col = Integer.parseInt(mA1B1.group(2));
    75       useA1B1 = true;
    76     }   
    77 
    78     boolean valid = true;
    79     if (row < 1 || row > maxRows)
    80     {
    81       if (useA1B1)
    82       {
    83         section.addErrorMessage("Row coordinate "+(row<1?"<A" : ">"+Coordinate.numericToAlpha(maxRows))+" in JSON: "+entryKey+"="+value);
    84       }
    85       else
    86       {
    87         section.addErrorMessage("Row coordinate "+(row<1?"<1" : ">"+maxRows)+" in JSON: "+entryKey+"="+value);
    88       }
    89       valid = false;
    90     }
    91     if (col < 1 || col > maxCols)
    92     {
    93       section.addErrorMessage("Column coordinate "+(col<1?"<1" : ">"+maxCols)+" in JSON: "+entryKey+"="+value);
    94       valid = false;
    9586    }
    9687   
    97     return valid ? new PlateCoordinate(row-1, col-1) : null;
     88    section.addErrorMessage("Invalid plate well in JSON: "+entryKey+"="+value);
     89    return null;
    9890  }
    9991 
     
    10496  }
    10597
     98  /**
     99    Handles variations in coordinate systems.
     100    @since 4.33.5
     101  */
     102  static enum CoordinateSystem
     103  {
     104    /**
     105      Both coordinates are numeric. Eg. 1:1, 2:1
     106     */
     107    NUMERIC(Pattern.compile("(\\d+)\\:(\\d+)"), false, false),
     108    /**
     109      The first (row) coordinate is alphabetic: A:1, B:2, etc.
     110    */
     111    ALPHA_NUMERIC(Pattern.compile("([A-Z]+)\\:(\\d+)"), true, false),
     112    /**
     113      The second (column) coordinate is alphabetic: 1:A, 2:B, etc.
     114    */
     115    NUMERIC_ALPHA(Pattern.compile("(\\d+)\\:([A-Z]+)"), false, true);
     116   
     117    private final Pattern p;
     118    private final boolean rowAlpha;
     119    private final boolean colAlpha;
     120   
     121    private CoordinateSystem(Pattern p, boolean rowAlpha, boolean colAlpha)
     122    {
     123      this.p = p;
     124      this.rowAlpha = rowAlpha;
     125      this.colAlpha = colAlpha;
     126    }
     127   
     128    Matcher matcher(String value)
     129    {
     130      return p.matcher(value);
     131    }
     132   
     133    int getRow(Matcher m)
     134    {
     135      String r = m.group(1);
     136      return rowAlpha ? Coordinate.alphaToNumeric(r) : Integer.parseInt(r);
     137    }
     138
     139    int getCol(Matcher m)
     140    {
     141      String c = m.group(2);
     142      return colAlpha ? Coordinate.alphaToNumeric(c) : Integer.parseInt(c);
     143    }
     144
     145    String row(int row)
     146    {
     147      return rowAlpha ? Coordinate.numericToAlpha(row) : Integer.toString(row);
     148    }
     149   
     150    String col(int col)
     151    {
     152      return colAlpha ? Coordinate.numericToAlpha(col) : Integer.toString(col);
     153    }
     154  }
    106155}
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/ProtocolValidator.java

    r6338 r6510  
    5353  public Protocol isValid(DbControl dc, String externalRef, JsonSection section, String entryKey)
    5454  {
    55     // TODO -- we hope that we will get some kind of ID value
    56     // externalRef = PatternValidator.CMD_ID.isValid(dc, externalRef, section, entryKey);
     55    externalRef = PatternValidator.CMD_PROTOCOL.isValid(dc, externalRef, section, entryKey);
    5756    if (externalRef == null) return null;
    5857
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/RnaInfo.java

    r6344 r6510  
    22
    33import java.util.Date;
     4import java.util.List;
     5
     6import net.sf.basedb.core.DbControl;
     7import net.sf.basedb.core.Extract;
     8import net.sf.basedb.core.ItemQuery;
    49import net.sf.basedb.core.Protocol;
     10import net.sf.basedb.core.Type;
    511import net.sf.basedb.core.data.PlateCoordinate;
     12import net.sf.basedb.core.query.Annotations;
     13import net.sf.basedb.core.query.Expressions;
     14import net.sf.basedb.core.query.Hql;
     15import net.sf.basedb.core.query.Restrictions;
     16import net.sf.basedb.reggie.Reggie;
     17import net.sf.basedb.reggie.dao.Annotationtype;
     18import net.sf.basedb.reggie.dao.Subtype;
     19import net.sf.basedb.util.Coordinate;
    620
    721/**
     
    1832  public Date qiacubeDate;
    1933  public Integer qiacubePos;
     34  public String qiacubeRunId;
    2035  public Integer qiacubeRunNumber;
    2136  public String operator;
    22   public Float rinOrRqs;
     37  public Float rin;
    2338  public Float qubitConc;
    2439
     
    2641  public boolean valid;
    2742 
    28   public RnaInfo(JsonSection section)
     43  public RnaInfo(JsonSection section, ImportContext ctx)
    2944  {
    3045    if (section != null)
     
    3550      operator = section.getOptionalEntry("Qiacube operator", null);
    3651     
    37       // TODO - qiacube run number
    38       // TODO -- concentrations and quantities
     52      qiacubeRunId = section.getRequiredEntry("Qiacube run number", PatternValidator.CMD_ID);
     53      if (qiacubeRunId != null && qiacubePos != null && ctx != null)
     54      {
     55        JsonSection duplicate = ctx.add("Qiacube:"+qiacubeRunId+":"+qiacubePos, section);
     56        if (duplicate != null)
     57        {
     58          String coordinate = (tmp.getRow()+1)+":"+Coordinate.numericToAlpha(tmp.getColumn()+1);
     59          String msg = "Qiacube position ["+coordinate+"] duplicated in file: ";
     60          section.addErrorMessage(msg+duplicate.getFile().getName());
     61          duplicate.addErrorMessage(msg+section.getFile().getName());
     62        }
     63      }
     64      if (qiacubeDate != null && qiacubePos != null && qiacubeRunId != null)
     65      {
     66        qiacubeRunNumber = findQiacubeRunNumber(qiacubeDate, qiacubeRunId, qiacubePos, section);
     67      }
     68     
    3969      qubitConc = section.getRequiredEntry("Concentration (ng/ul)", FloatValidator.POSITIVE);
    40       // TODO -- RNAQC
    41       // TODO -- protocol
     70      rin = section.getRequiredEntry("RIN", FloatValidator.RIN);
    4271      protocol = section.getRequiredEntry("Protocol", ProtocolValidator.EXTRACTION_PROTOCOL);
     72
     73      // TODO -- implementation is needed
     74      section.getOptionalEntry("Box and position", NullValidator.warnIfNull(String.class));
     75      section.getOptionalEntry("Original quantity", NullValidator.warnIfNull(Number.class));
     76      section.getOptionalEntry("Remaining quantity", NullValidator.warnIfNull(Number.class));
     77      section.getOptionalEntry("RNA ID", NullValidator.warnIfNull(String.class));
    4378    }
    4479    valid = section != null && !section.hasError();
    4580  }
    4681 
     82  /**
     83    Find the Qiacube run number. We will look for existing RNA items on the given
     84    date. If we find a match with the same QiacubeRunId we use that same run number.
     85    But! If the match happens to be on the same position and error is triggered.
     86    If we find RNA on the same date with no or different QiacubeRunId we use
     87    the max existing run number +1. If not matched RNA is found, the run number is 1.
     88  */
     89  private Integer findQiacubeRunNumber(Date qiacubeDate, String qiacubeRunId, Integer qiacubePos, JsonSection section)
     90  {
     91    ItemQuery<Extract> query = Extract.getQuery();
     92    DbControl dc = section.getFile().dc();
     93    query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     94    Subtype.RNA.addFilter(dc, query);
     95    query.join(Annotations.innerJoin(null, Annotationtype.QIACUBE_DATE.load(dc), "qcdate"));
     96    query.restrict(Restrictions.eq(Hql.alias("qcdate"), Expressions.parameter("qcdate", qiacubeDate, Type.DATE)));
     97   
     98    List<Extract> list = query.list(dc);   
     99    Integer runNumberSameId = null;
     100    Integer runNumberSameDate = null;
     101    for (Extract rna : list)
     102    {
     103      String runId = (String)Annotationtype.QIACUBE_RUN_ID.getAnnotationValue(dc, rna);
     104      Integer pos = (Integer)Annotationtype.QIACUBE_POSITION.getAnnotationValue(dc, rna);
     105      Integer runNumber = (Integer)Annotationtype.QIACUBE_RUN_NO.getAnnotationValue(dc, rna);
     106      if (pos == null || runNumber == null) continue; // Should not happen if everything is correctly registered!
     107     
     108      if (qiacubeRunId.equals(runId))
     109      {
     110        runNumberSameId = runNumber;
     111        if (qiacubePos.equals(pos))
     112        {
     113          section.addErrorMessage("Found existing RNA on Qiacube position "+pos+": "+rna.getName());
     114        }
     115      }
     116      else
     117      {
     118        if (runNumberSameDate == null || runNumber > runNumberSameDate)
     119        {
     120          runNumberSameDate = runNumber;
     121        }
     122      }
     123    }
     124    return runNumberSameId != null ? runNumberSameId : (runNumberSameDate != null ? runNumberSameDate+1 : 1);
     125  }
    47126}
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/ScanBIdRef.java

    r6351 r6510  
    22
    33import net.sf.basedb.core.DbControl;
     4import net.sf.basedb.core.PermissionDeniedException;
     5import net.sf.basedb.reggie.dao.Case;
    46import net.sf.basedb.reggie.dao.Rna;
    57import net.sf.basedb.reggie.dao.SpecimenTube;
     
    1214    and it shoult not have existing child items.
    1315  * Specimen: An existing specimen with the exact name should already exist.
    14   * Case: TODO -- Either an existing FutureSpecimen or an existing Case
     16  * Case: A new specimen is created for the given case. The case may or may not already exist.
    1517   
    1618  @since 4.32
     
    2426  public Rna rna;
    2527  public SpecimenTube specimen;
     28  public Case theCase;
    2629 
    2730  public ScanBIdRef()
     
    4346      id = value;
    4447     
    45       if (value.matches("\\d{7}"))
     48      if (value.matches("\\d{7}(C|D)?"))
    4649      {
    47         // 7 digits is a SCAN-B CASE ID
     50        // 7 digits is a SCAN-B CASE ID with optional 'C' or 'D' suffix
    4851        idType = SampleIdType.CASE;
    49         // TODO -- load Case or FutureSpecimen
    5052      }
    5153      else if (value.matches("\\d{7}\\.\\d"))
     
    8183        section.addErrorMessage("Invalid SCANB_ID: " + id);
    8284      }
     85     
     86      // Check if a Case already exists (but in most cases it won't)
     87      if (idType != null)
     88      {
     89        theCase = Case.findByName(dc, id);
     90        if (theCase != null)
     91        {
     92          try
     93          {
     94            theCase.verifyConsent(dc, null);
     95          }
     96          catch (PermissionDeniedException ex)
     97          {
     98            section.addErrorMessage(ex.getMessage());
     99          }
     100        }
     101      }
    83102    }
    84103    return this;
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/SpecimenInfo.java

    r6458 r6510  
    1717{
    1818  public String pad;
     19  public String clarityId;
    1920 
    2021  public Date arrivalDate;
     
    4243      if (main.idRef != null && main.idRef.idType == SampleIdType.CASE)
    4344      {
    44         pad = section.getRequiredEntry("PAD", PatternValidator.PAD);
     45        numberOfPieces = section.getOptionalEntry("Number of pieces", NullValidator.warnIfNull(IntValidator.POSITIVE.warnIf(1, 10)));
     46        numberOfTubes = section.getOptionalEntry("Number of tubes", NullValidator.warnIfNull(IntValidator.POSITIVE.warnIf(1, 4)));
     47        laterality = section.getOptionalEntry("Laterality", NullValidator.warnIfNull(EnumValidator.LATERALITY));
    4548       
    46         arrivalDate = section.getRequiredEntry("Arrival date", DateValidator.YYYY_MM_DD.warnIfFutureOrOlder(365));
    47         samplingDateTime = section.getRequiredEntry("Sampling date + time", DateValidator.YYYY_MM_DD_HH_MM.warnIfFutureOrOlder(365));
    48         rnaLaterDateTime = section.getRequiredEntry("RNA later date + time", DateValidator.YYYY_MM_DD_HH_MM.warnIfFutureOrOlder(samplingDateTime));
     49        samplingDateTime = section.getOptionalEntry("Sampling date", DateValidator.YYYY_MM_DD_HH_MM.warnIfFutureOrOlder(365));
     50        rnaLaterDateTime = section.getOptionalEntry("RNA later date + time", DateValidator.YYYY_MM_DD_HH_MM.warnIfFutureOrOlder(samplingDateTime));
     51       
     52        pad = section.getOptionalEntry("Sample Name", PatternValidator.PAD);
     53        clarityId = section.getRequiredEntry("Clarity ID", PatternValidator.CLARITY_ID);
     54        arrivalDate = section.getRequiredEntry("Date of arrival", DateValidator.YYYY_MM_DD.warnIfFutureOrOlder(365));
     55
     56        biopsyType = section.getOptionalEntry("Sample type", EnumValidator.BIOPSY_TYPE);
     57        if (biopsyType == null)
     58        {
     59          if (main.idRef.id.endsWith("C"))
     60          {
     61            biopsyType = "SpecimenCoreBiopsy";
     62          }
     63          else if (main.idRef.id.endsWith("D"))
     64          {
     65            biopsyType = "SpecimenCoreBiopsy2nd";
     66          }
     67        }
     68        specimenType = section.getOptionalEntry("Specimen type", EnumValidator.SPECIMEN_TYPE);
     69
     70        pathologyNote = section.getOptionalEntry("Sample description", null);
     71        deliveryComment = section.getOptionalEntry("Sample comment", null);
    4972      }
    5073     
    51 // TODO -- implement in JSON files   
    52 //      originalQuantity = section.getRequiredEntry("Original quantity (mg)", FloatValidator.POSITIVE);
    53 //      remainingQuantity = section.getRequiredEntry("Remaining quantity (mg)", FloatValidator.POSITIVE);
     74      originalQuantity = section.getOptionalEntry("Original quantity (mg)", NullValidator.warnIfNull(FloatValidator.POSITIVE));
     75      remainingQuantity = section.getOptionalEntry("Remaining quantity (mg)", NullValidator.warnIfNull(FloatValidator.POSITIVE));
    5476     
    55 //      laterality = section.getRequiredEntry("Laterality", EnumValidator.LATERALITY);
    56       specimenType = section.getOptionalEntry("Specimen type", EnumValidator.SPECIMEN_TYPE);
    57       biopsyType = section.getOptionalEntry("Biopsy type", EnumValidator.BIOPSY_TYPE);
    58      
    59 //      numberOfTubes = section.getRequiredEntry("Number of delivered tubes", IntValidator.POSITIVE.warnIf(1, 4));
    60 //      numberOfPieces = section.getRequiredEntry("Number of pieces", IntValidator.POSITIVE.warnIf(1, 10));
    61      
    62       pathologyNote = section.getOptionalEntry("Other pathology note", null);
    63       deliveryComment = section.getOptionalEntry("Sample comment", null);
    64      
    65       // TODO -- box/box pos/label
    66      
     77      // TODO -- implementation is needed
     78      section.getOptionalEntry("Box and position", NullValidator.warnIfNull(String.class));
     79      section.getOptionalEntry("Specimen ID", NullValidator.warnIfNull(String.class));
     80
    6781      // TODO -- check agains existing specimen and warn if values differ?
    68      
    6982      if (originalQuantity != null && remainingQuantity != null && remainingQuantity+0.1 > originalQuantity)
    7083      {
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/BloodFollowUpRegistrationServlet.java

    r6329 r6510  
    404404      Restrictions.or(
    405405        Subtype.SPECIMEN.restriction(dc, null),
    406         Subtype.NO_SPECIMEN.restriction(dc, null),
    407         Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     406        Subtype.NO_SPECIMEN.restriction(dc, null)
    408407      ));
    409408    sampleQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/CaseSummaryServlet.java

    r6479 r6510  
    5858import net.sf.basedb.reggie.dao.FlowCell;
    5959import net.sf.basedb.reggie.dao.FlowThrough;
    60 import net.sf.basedb.reggie.dao.FutureSpecimen;
    6160import net.sf.basedb.reggie.dao.GenotypeCall;
    6261import net.sf.basedb.reggie.dao.Histology;
     
    307306        }
    308307       
    309         List<FutureSpecimen> futureSpecimen = FutureSpecimen.findByCaseName(dc, caseName, false);
    310         if (futureSpecimen.size() > 0)
    311         {
    312           JSONArray jsonFutureSpecimen = new JSONArray();
    313           for (FutureSpecimen fs : futureSpecimen)
    314           {
    315             loadFutureSpecimenInfo(dc, fs);
    316             jsonFutureSpecimen.add(fs.asJSONObject());
    317           }
    318           jsonSections.add(loadSectionInfo(sc, "futurespecimen"));
    319           json.put("futureSpecimen", jsonFutureSpecimen);
    320         }
    321        
    322308        List<Histology> histology = Histology.findByCaseName(dc, caseName);
    323309        if (histology.size() > 0)
     
    768754  }
    769755
    770   private void loadFutureSpecimenInfo(DbControl dc, FutureSpecimen futureSpecimen)
    771   {
    772     Sample s = futureSpecimen.getSample();
    773     futureSpecimen.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
    774     futureSpecimen.setAnnotation("editable", s.hasPermission(Permission.WRITE));
    775    
    776     futureSpecimen.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
    777     futureSpecimen.loadAnnotations(dc, "pad", Annotationtype.PAD, null);
    778     futureSpecimen.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME,  Reggie.CONVERTER_DATETIME_TO_STRING);
    779     futureSpecimen.loadAnnotations(dc, "rnaLaterDate", Annotationtype.RNALATER_DATETIME,  Reggie.CONVERTER_DATETIME_TO_STRING);
    780     futureSpecimen.loadAnnotations(dc, "biopsyType", Annotationtype.BIOPSY_TYPE, null);
    781     futureSpecimen.setAnnotation("comment", s.getDescription());
    782   }
    783  
    784756  private void loadGenotypeCallInfo(DbControl dc, GenotypeCall gtc)
    785757  {
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ExportServlet.java

    r6474 r6510  
    166166            Restrictions.or(
    167167              Subtype.SPECIMEN.restriction(dc, null),
    168               Subtype.NO_SPECIMEN.restriction(dc, null),
    169               Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     168              Subtype.NO_SPECIMEN.restriction(dc, null)
    170169            ));
    171170        }
     
    179178              Subtype.SPECIMEN.restriction(dc, null),
    180179              Subtype.NO_SPECIMEN.restriction(dc, null),
    181               Subtype.FUTURE_SPECIMEN.restriction(dc, null),
    182180              Subtype.BLOOD.restriction(dc, null)
    183181            ));
     
    251249          ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc);
    252250          ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc);
    253           ItemSubtype subtypeFutureSpecimen = Subtype.FUTURE_SPECIMEN.load(dc);
    254251          ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc);
    255252
     
    276273              consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, s);
    277274            }
    278             else if (subtypeSpecimen.equals(sampleType) || subtypeNoSpecimen.equals(sampleType) || subtypeFutureSpecimen.equals(sampleType))
     275            else if (subtypeSpecimen.equals(sampleType) || subtypeNoSpecimen.equals(sampleType))
    279276            {
    280277              // The parent is the 'Case' and the grandparent is the 'Patient' for specimens and no specimens
     
    752749    ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc);
    753750    ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc);
    754     ItemSubtype subtypeFutureSpecimen = Subtype.FUTURE_SPECIMEN.load(dc);
    755751    ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc);
    756752   
     
    783779      sampleType.equals("specimen_nospecimen"))
    784780    {
    785       // Include 'Specimen', 'No specimen' and 'FutureSpecimen' items
     781      // Include 'Specimen' and 'No specimen' items
    786782      sampleQuery.restrict(
    787783        Restrictions.or(
    788784          Subtype.SPECIMEN.restriction(dc, null),
    789           Subtype.NO_SPECIMEN.restriction(dc, null),
    790           Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     785          Subtype.NO_SPECIMEN.restriction(dc, null)
    791786        ));
    792787      sampleQuery.join(Hql.innerJoin(null, "parent", "cse", true));
     
    868863      if (biopsyType == null)
    869864      {
    870         if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype) || subtypeFutureSpecimen.equals(sampleSubtype))
     865        if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype))
    871866        {
    872867          biopsyType = "default";
     
    898893          patient = s.getParent();
    899894        }
    900         else if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype) || subtypeFutureSpecimen.equals(sampleSubtype))
     895        else if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype))
    901896        {
    902897          // The grandparent is the 'Patient' for specimens and no specimens
     
    917912        }
    918913      }
    919       if (sampleSubtype.equals(subtypeSpecimen) || sampleSubtype.equals(subtypeFutureSpecimen))
     914      if (sampleSubtype.equals(subtypeSpecimen))
    920915      {
    921916        // Get PAD reference
     
    12731268          "\t" + patientAllFirstNames +
    12741269          "\t" + patientFamilyName;
    1275       if (subtype != null && (subtype.equals("Specimen") || subtype.equals("NoSpecimen") || subtype.equals("FutureSpecimen")))
     1270      if (subtype != null && (subtype.equals("Specimen") || subtype.equals("NoSpecimen")))
    12761271      {
    12771272        returnStr += "\t" + padReference +
     
    16081603        Restrictions.or(
    16091604          Subtype.SPECIMEN.restriction(dc, null),
    1610           Subtype.NO_SPECIMEN.restriction(dc, null),
    1611           Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     1605          Subtype.NO_SPECIMEN.restriction(dc, null)
    16121606        ));
    16131607      specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     
    17701764 
    17711765  /**
    1772     Get the external (release) ID for all specimen, no-specimen or future-specimen
     1766    Get the external (release) ID for all specimen or no-specimen
    17731767    related to the patient.
    17741768  */
     
    17891783        Restrictions.or(
    17901784          Subtype.SPECIMEN.restriction(dc, null),
    1791           Subtype.NO_SPECIMEN.restriction(dc, null),
    1792           Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     1785          Subtype.NO_SPECIMEN.restriction(dc, null)
    17931786        ));
    17941787      specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     
    18861879        Restrictions.or(
    18871880          Subtype.SPECIMEN.restriction(dc, null),
    1888           Subtype.NO_SPECIMEN.restriction(dc, null),
    1889           Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     1881          Subtype.NO_SPECIMEN.restriction(dc, null)
    18901882        ));
    18911883      specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ImportServlet.java

    r6336 r6510  
    136136        findByPAD.join(Hql.innerJoin("cce", "event", "evt"));
    137137        findByPAD.join(Hql.innerJoin("evt", "bioMaterial", "sp")); // 'sp' should now reference a specimen tube/nospecimen
    138         // Restrict to 'Specimen', 'NoSpecimen' or 'FutureSpecimen' child items
    139         findByPAD.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, "sp"), Subtype.NO_SPECIMEN.restriction(dc, "sp"), Subtype.FUTURE_SPECIMEN.restriction(dc, "sp")));
     138        // Restrict to 'Specimen' or 'NoSpecimen' child items
     139        findByPAD.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, "sp"), Subtype.NO_SPECIMEN.restriction(dc, "sp")));
    140140       
    141141        findByPAD.join(Annotations.leftJoin("sp", Annotationtype.PAD.get(dc), "pad"));
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/InstallServlet.java

    r6477 r6510  
    281281        jsonChecks.add(checkSubtype(dc, Subtype.SPECIMEN,null, createIfMissing, Subtype.CASE));
    282282        jsonChecks.add(checkSubtype(dc, Subtype.NO_SPECIMEN,null, createIfMissing, Subtype.CASE));
    283         jsonChecks.add(checkSubtype(dc, Subtype.FUTURE_SPECIMEN,null, createIfMissing, Subtype.CASE));
    284283        jsonChecks.add(checkSubtype(dc, Subtype.TMA_SPECIMEN,null, createIfMissing, Subtype.CASE));
    285284        jsonChecks.add(checkSubtype(dc, Subtype.HISTOLOGY_PROTOCOL, null, createIfMissing));
     
    505504        jsonChecks.add(checkAnnotationType(dc, Annotationtype.QIACUBE_POSITION, 1, new ValueOptions(1, 12), createIfMissing, effectivePermissionsUse));
    506505        jsonChecks.add(checkAnnotationType(dc, Annotationtype.QIACUBE_RUN_NO, 1, new ValueOptions(1, null), createIfMissing, effectivePermissionsUse));
     506        jsonChecks.add(checkAnnotationType(dc, Annotationtype.QIACUBE_RUN_ID, 1, null, createIfMissing, effectivePermissionsUse));
    507507       
    508508        jsonChecks.add(checkAnnotationType(dc, Annotationtype.QC_RUN_DATE, 1, null, createIfMissing, effectivePermissionsUse));
     
    881881            Annotationtype.PAD, Annotationtype.RNALATER_DATETIME,
    882882            Annotationtype.SAMPLING_DATETIME, Annotationtype.SPECIMEN_TYPE,
     883            Annotationtype.EXTERNAL_REF,
    883884            Annotationtype.LINKED_SPECIMEN, Annotationtype.YELLOW_LABEL,
    884885            Annotationtype.COMPLETED_DATE,
     
    893894            ));
    894895       
    895         jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.FUTURE_SPECIMEN, createIfMissing,
    896             Annotationtype.BIOPSY_TYPE,
    897             Annotationtype.LATERALITY,
    898             Annotationtype.PAD,
    899             Annotationtype.SAMPLING_DATETIME, Annotationtype.RNALATER_DATETIME,
    900             Annotationtype.OTHER_PATH_NOTE,
    901             Annotationtype.LINKED_SPECIMEN, Annotationtype.DO_NOT_USE, Annotationtype.DO_NOT_USE_COMMENT,
    902             Annotationtype.AUTO_PROCESSING
    903             ));
    904 
    905896        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.TMA_SPECIMEN, createIfMissing,
    906897            Annotationtype.TMA_BLOCK, Annotationtype.TMA_BLOCK_POS,
     
    937928        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.RNA, createIfMissing,
    938929            Annotationtype.QIACUBE_DATE, Annotationtype.QIACUBE_OPERATOR,
    939             Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO,
     930            Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO, Annotationtype.QIACUBE_RUN_ID,
    940931            Annotationtype.ND_CONC, Annotationtype.ND_260_BY_280, Annotationtype.ND_260_BY_230,
    941932            Annotationtype.QUBIT_CONC,
     
    961952        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.DNA, createIfMissing,
    962953            Annotationtype.QIACUBE_DATE, Annotationtype.QIACUBE_OPERATOR,
    963             Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO,
     954            Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO, Annotationtype.QIACUBE_RUN_ID,
    964955            Annotationtype.ND_CONC, Annotationtype.ND_260_BY_280, Annotationtype.ND_260_BY_230,
    965956            Annotationtype.QUBIT_CONC,
     
    991982        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.FLOW_THROUGH, createIfMissing,
    992983            Annotationtype.QIACUBE_DATE, Annotationtype.QIACUBE_OPERATOR,
    993             Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO,
     984            Annotationtype.QIACUBE_POSITION, Annotationtype.QIACUBE_RUN_NO, Annotationtype.QIACUBE_RUN_ID,
    994985            Annotationtype.ALLPREP_MINI_KIT, Annotationtype.ETOH70,
    995986            Annotationtype.BUFFER_RW1, Annotationtype.BUFFER_RPE,
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/LinkedSpecimenServlet.java

    r6336 r6510  
    120120
    121121        // Load all patients and cases that have at least one
    122         // specimen/nospecimen/futurespecimen without creation date
     122        // specimen/nospecimen without creation date
    123123        ItemQuery<Sample> queryNoDate = Sample.getQuery();
    124124        queryNoDate.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     
    126126          Restrictions.or(
    127127            Subtype.SPECIMEN.restriction(dc, null),
    128             Subtype.NO_SPECIMEN.restriction(dc, null),
    129             Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     128            Subtype.NO_SPECIMEN.restriction(dc, null)
    130129          ));
    131130        queryNoDate.join(Hql.innerJoin(null, "parent", "c", null, true));
     
    136135        queryNoDate.restrict(Restrictions.eq(Hql.property("ce", "eventDate"), null));
    137136       
    138         // Load all specimen/nospecimen/futurespecimen with a known creation date
     137        // Load all specimen/nospecimen with a known creation date
    139138        // IMPORTANT!! Sort by oldest first
    140139        ItemQuery<Sample> queryHasDate = Sample.getQuery();
     
    143142          Restrictions.or(
    144143            Subtype.SPECIMEN.restriction(dc, null),
    145             Subtype.NO_SPECIMEN.restriction(dc, null),
    146             Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     144            Subtype.NO_SPECIMEN.restriction(dc, null)
    147145          ));
    148146        queryHasDate.join(Hql.innerJoin(null, "parent", "c", null, true));
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/PersonalRegistrationServlet.java

    r6329 r6510  
    3333import net.sf.basedb.core.query.Expressions;
    3434import net.sf.basedb.core.query.Hql;
     35import net.sf.basedb.core.query.Orders;
    3536import net.sf.basedb.core.query.Restrictions;
    3637import net.sf.basedb.reggie.JsonUtil;
     
    4445import net.sf.basedb.reggie.dao.Case;
    4546import net.sf.basedb.reggie.dao.Consent;
    46 import net.sf.basedb.reggie.dao.FutureSpecimen;
    4747import net.sf.basedb.reggie.dao.NoSpecimen;
    4848import net.sf.basedb.reggie.dao.Patient;
     
    9494        json.put("count", count);
    9595      }
     96      else if ("GetSpecimenWithoutCase".equals(cmd))
     97      {
     98        dc = sc.newDbControl(":Pathology referral form registration");
     99     
     100        ItemQuery<Sample> query = Sample.getQuery();
     101        Subtype.SPECIMEN.addFilter(dc, query);
     102        query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     103        query.restrict(Restrictions.eq(Hql.property("parent"), null));
     104        // Filter on externalId to get rid of external samples that never get a parent item
     105        query.restrict(Restrictions.like(Hql.property("externalId"), Expressions.string(Subtype.SPECIMEN.getExternalIdPrefix()+"%")));
     106        query.order(Orders.asc(Hql.property("name")));
     107
     108        List<SpecimenTube> specimenTubes = SpecimenTube.toList(query.list(dc));
     109        JSONArray jsonSpecimenTubes = new JSONArray();
     110        String lastCaseName = null;
     111        JSONObject jsonCase = null;
     112        int numSpecimenForLastCase = 0;
     113        for (SpecimenTube tube : specimenTubes)
     114        {
     115          String caseName = tube.getName().substring(0, 7);
     116          String biopsyType = (String)Annotationtype.BIOPSY_TYPE.getAnnotationValue(dc, tube.getItem());
     117          String externalRef = (String)Annotationtype.EXTERNAL_REF.getAnnotationValue(dc, tube.getItem());
     118          if ("SpecimenCoreBiopsy".equals(biopsyType))
     119          {
     120            caseName += "C";
     121          }
     122          else if ("SpecimenCoreBiopsy2nd".equals(biopsyType))
     123          {
     124            caseName += "D";
     125          }
     126          if (!caseName.equals(lastCaseName))
     127          {
     128            numSpecimenForLastCase = 1;
     129            jsonCase = new JSONObject();
     130            jsonCase.put("name", caseName);
     131            lastCaseName = caseName;
     132            jsonSpecimenTubes.add(jsonCase);
     133          }
     134          else
     135          {
     136            numSpecimenForLastCase++;
     137          }
     138          if (externalRef != null) jsonCase.put("externalRef", externalRef);
     139          jsonCase.put("numSpecimen", numSpecimenForLastCase);
     140        }
     141        json.put("specimenTubes", jsonSpecimenTubes);
     142      }
    96143      else if ("GetCaseInfo".equals(cmd))
    97144      {
     
    118165        List<SpecimenTube> specimenTubes = null;
    119166        NoSpecimen noSpecimen = null;
    120         FutureSpecimen futureSpecimen = null;
    121167        JSONObject jsonCase = null;
    122168        JSONObject jsonBlood = null;
     
    149195            {
    150196              noSpecimen = nsList.get(0);
    151             }
    152            
    153             if (noSpecimen == null)
    154             {
    155               // Also check if there are any 'FutureSpecimen' items
    156               List<FutureSpecimen> fsList = FutureSpecimen.findByCase(dc, theCase, caseName, site.useCaseSuffixForPreNeoForms());
    157               if (fsList.size() > 1)
    158               {
    159                 // There should be at most one 'NoSpecimen' item
    160                 throw new InvalidDataException(
    161                   "Found " + fsList.size() + " 'FutureSpecimen' samples for the case (" + caseName +
    162                   "). This wizard can't be used until that is corrected.");
    163               }
    164               else if (fsList.size() == 1)
    165               {
    166                 futureSpecimen = fsList.get(0);
    167               }
    168197            }
    169198          }
     
    256285            tube.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
    257286            tube.loadAnnotations(dc, "rnaLaterDate", Annotationtype.RNALATER_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
     287            tube.loadAnnotations(dc, "biopsyType", Annotationtype.BIOPSY_TYPE, null);
     288            tube.loadAnnotations(dc, "specimenType", Annotationtype.SPECIMEN_TYPE, null);
     289            tube.loadAnnotations(dc, "otherPathNote", Annotationtype.OTHER_PATH_NOTE, null);
     290            tube.loadAnnotations(dc, "operatorDeliveryComment", Annotationtype.OPERATOR_DELIVERY_COMMENT, null);
    258291            jsonTubes.add(tube.asJSONObject());
    259292          }
     
    267300          noSpecimen.loadAnnotations(dc, "reasonIfNoSpecimen", Annotationtype.REASON_IF_NO_SPECIMEN, null);
    268301          jsonCase.put("noSpecimen", noSpecimen.asJSONObject());
    269         }
    270        
    271         if (futureSpecimen != null)
    272         {
    273           futureSpecimen.loadAnnotations(dc, "pad", Annotationtype.PAD, null);
    274           futureSpecimen.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
    275           futureSpecimen.loadAnnotations(dc, "rnaLaterDate", Annotationtype.RNALATER_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
    276           futureSpecimen.loadAnnotations(dc, "otherPathNote", Annotationtype.OTHER_PATH_NOTE, null);
    277           jsonCase.put("futureSpecimen", futureSpecimen.asJSONObject());       
    278302        }
    279303       
     
    505529            if (samplingDateTime != null) Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, specimen, samplingDateTime);
    506530            if (rnaLaterDateTime != null) Annotationtype.RNALATER_DATETIME.setAnnotationValue(dc, specimen, rnaLaterDateTime);
     531            Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("otherPathNote")));
     532            Annotationtype.OPERATOR_DELIVERY_COMMENT.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("operatorDeliveryComment")));
     533            Annotationtype.SPECIMEN_TYPE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("specimenType")));
     534            Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("biopsyType")));
     535
    507536            String yellowLabel = (String)jsonSpec.get("YellowLabel");
    508537            String yellowLabelOriginal = (String)jsonSpec.get("YellowLabelOriginal");
     
    520549        else
    521550        {
    522           Subtype newSpecimenType = Subtype.getByCName((String)jsonCase.get("newSpecimenType"));         
    523 
    524           // Create new 'NoSpecimen' or 'FutureSpecimen' item
    525           Sample newSpecimen = Sample.getNew(dc);
    526           newSpecimen.setName(SpecimenTube.getNextSpecimenName(dc, originalCaseName));
    527           newSpecimen.setExternalId(SpecimenTube.getNextExternalId(dc, newSpecimenType));
    528           newSpecimen.setItemSubtype(newSpecimenType.load(dc));
    529           dc.saveItem(newSpecimen);
    530           BioMaterialEvent creationEvent = newSpecimen.getCreationEvent();
     551          Date samplingDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonCase.get("samplingDate"));
     552          if (samplingDate != null)
     553          {
     554            // Create a SAMPLING_DATE reference date and check if it should replace the existing
     555            refDate = refDate.getThisOrTheReplacement(new ReferenceDateWithSource(samplingDate, ReferenceDateSource.SAMPLING_DATE));
     556          }
     557
     558          // Create new 'NoSpecimen' item
     559          Sample noSpecimen = Sample.getNew(dc);
     560          noSpecimen.setName(SpecimenTube.getNextSpecimenName(dc, originalCaseName));
     561          noSpecimen.setExternalId(SpecimenTube.getNextExternalId(dc, Subtype.NO_SPECIMEN));
     562          noSpecimen.setItemSubtype(Subtype.NO_SPECIMEN.load(dc));
     563          dc.saveItem(noSpecimen);
     564          BioMaterialEvent creationEvent = noSpecimen.getCreationEvent();
    531565          creationEvent.setSource(theCase);
    532          
    533           if (laterality != null) Annotationtype.LATERALITY.setAnnotationValue(dc, newSpecimen, laterality);
    534           Annotationtype.PAD.setAnnotationValue(dc, newSpecimen, pad);
    535           Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, newSpecimen, Values.getStringOrNull((String)jsonCase.get("biopsyType")));
    536          
    537           if (newSpecimenType == Subtype.NO_SPECIMEN)
    538           {
    539             Annotationtype.REASON_IF_NO_SPECIMEN.setAnnotationValue(dc, newSpecimen, Values.getStringOrNull((String)jsonCase.get("reasonIfNoSpecimen")));
    540             Date samplingDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonCase.get("samplingDate"));
    541             Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, newSpecimen, samplingDate);
    542             creationEvent.setEventDate(samplingDate);
    543             if (samplingDate != null)
    544             {
    545               // Create a SAMPLING_DATE reference date and check if it should replace the existing
    546               refDate = refDate.getThisOrTheReplacement(new ReferenceDateWithSource(samplingDate, ReferenceDateSource.SAMPLING_DATE));
    547             }
    548           }
    549           else if (newSpecimenType == Subtype.FUTURE_SPECIMEN)
    550           {
    551             Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, newSpecimen, Values.getStringOrNull((String)jsonCase.get("otherPathNote")));
    552             Date rnaLaterDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("rnaLaterDate"));
    553             Date samplingDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("samplingDate"));
    554             Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, newSpecimen, samplingDateTime);
    555             Annotationtype.RNALATER_DATETIME.setAnnotationValue(dc, newSpecimen, rnaLaterDateTime);
    556             creationEvent.setEventDate(samplingDateTime);
    557             if (samplingDateTime != null)
    558             {
    559               // Create a SAMPLING_DATE reference date and check if it should replace the existing
    560               refDate = refDate.getThisOrTheReplacement(new ReferenceDateWithSource(samplingDateTime, ReferenceDateSource.SAMPLING_DATE));
    561             }
    562           }
    563          
    564           jsonMessages.add(newSpecimenType.getName()+" '" + newSpecimen.getName() + "' created successfully.");
     566          creationEvent.setEventDate(samplingDate);
     567         
     568          if (laterality != null) Annotationtype.LATERALITY.setAnnotationValue(dc, noSpecimen, laterality);
     569          Annotationtype.PAD.setAnnotationValue(dc, noSpecimen, pad);
     570          Annotationtype.REASON_IF_NO_SPECIMEN.setAnnotationValue(dc, noSpecimen, Values.getStringOrNull((String)jsonCase.get("reasonIfNoSpecimen")));
     571          Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, noSpecimen, samplingDate);
     572          Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, noSpecimen, Values.getStringOrNull((String)jsonCase.get("biopsyType")));
     573         
     574          jsonMessages.add("NoSpecimen '" + noSpecimen.getName() + "' created successfully.");
    565575        }
    566576       
     
    611621        JSONArray jsonSpecimen = (JSONArray)jsonCase.get("specimen");
    612622        JSONObject jsonNoSpecimen = (JSONObject)jsonCase.get("noSpecimen");
    613         JSONObject jsonFutureSpecimen = (JSONObject)jsonCase.get("futureSpecimen");
    614623     
    615624        Set<SharedItem> itemsToPublish = new HashSet<>();
     
    624633          ItemQuery<Sample> childQuery = theCase.getChildSamples();
    625634          childQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
    626           childQuery.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, null), Subtype.NO_SPECIMEN.restriction(dc, null), Subtype.FUTURE_SPECIMEN.restriction(dc, null)));
    627          
    628           int numChildren = 0;
     635          childQuery.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, null), Subtype.NO_SPECIMEN.restriction(dc, null)));
     636         
     637          int numUpdated = 0;
    629638          for (Sample child : childQuery.list(dc))
    630639          {
    631             Annotationtype.LATERALITY.setAnnotationValue(dc, child, laterality);
    632             numChildren++;
    633           }
    634          
    635           if (numChildren > 0)
    636           {
    637             jsonMessages.add("Updated laterality on " + numChildren + " child Specimen/NoSpecimen/FutureSpecimen items.");
    638           }
    639          
     640            if (Annotationtype.LATERALITY.setAnnotationValue(dc, child, laterality))
     641            {
     642              numUpdated++;
     643            }
     644          }
     645          if (numUpdated > 0)
     646          {
     647            jsonMessages.add("Updated laterality on " + numUpdated + " child Specimen/NoSpecimen items.");
     648          }
    640649        }
    641650     
     
    647656          Date samplingDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("samplingDate"));
    648657          Date rnaLaterDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("rnaLaterDate"));
     658          String otherPathNote = (String)jsonCase.get("otherPathNote");
    649659         
    650660          if (samplingDateTime != null)
     
    671681            if (samplingDateTime != null) Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, specimen, samplingDateTime);
    672682            if (rnaLaterDateTime != null) Annotationtype.RNALATER_DATETIME.setAnnotationValue(dc, specimen, rnaLaterDateTime);
     683            Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("otherPathNote")));
     684            Annotationtype.OPERATOR_DELIVERY_COMMENT.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("operatorDeliveryComment")));
     685            Annotationtype.SPECIMEN_TYPE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("specimenType")));
     686            Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, specimen, Values.getStringOrNull((String)jsonSpec.get("biopsyType")));
    673687            String yellowLabel = (String)jsonSpec.get("YellowLabel");
    674688            String yellowLabelOriginal = (String)jsonSpec.get("YellowLabelOriginal");
     
    687701        else
    688702        {
    689           // Create or Update the 'NoSpecimen'/'FutureSpecimen' item
    690           Sample noOrFutureSpecimen = null;
    691           Subtype noOrFutureType = null;
     703          // Create or Update the 'NoSpecimen' item
     704          Date samplingDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonCase.get("samplingDate"));
     705          if (samplingDate != null)
     706          {
     707            refDate = refDate.getThisOrTheReplacement(new ReferenceDateWithSource(samplingDate, ReferenceDateSource.SAMPLING_DATE));
     708          }
     709
     710          Sample noSpecimen = null;
    692711          if (jsonNoSpecimen != null)
    693712          {
    694             noOrFutureSpecimen = Sample.getById(dc, ((Number)jsonNoSpecimen.get("id")).intValue());
    695             noOrFutureType = Subtype.NO_SPECIMEN;
    696             jsonMessages.add(noOrFutureType.getName() + " '" + noOrFutureSpecimen.getName() + "' updated successfully.");
    697           }
    698           else if (jsonFutureSpecimen != null)
    699           {
    700             noOrFutureSpecimen = Sample.getById(dc, ((Number)jsonFutureSpecimen.get("id")).intValue());
    701             noOrFutureType = Subtype.FUTURE_SPECIMEN;
    702             jsonMessages.add(noOrFutureType.getName() + " '" + noOrFutureSpecimen.getName() + "' updated successfully.");
     713            noSpecimen = Sample.getById(dc, ((Number)jsonNoSpecimen.get("id")).intValue());
    703714          }
    704715          else
    705716          {
    706             noOrFutureType = Subtype.getByCName((String)jsonCase.get("newSpecimenType"));
    707             noOrFutureSpecimen = Sample.getNew(dc);
    708             noOrFutureSpecimen.setName(SpecimenTube.getNextSpecimenName(dc, originalCaseName));
    709             noOrFutureSpecimen.setExternalId(SpecimenTube.getNextExternalId(dc, noOrFutureType));
    710             noOrFutureSpecimen.setItemSubtype(noOrFutureType.load(dc));
    711             noOrFutureSpecimen.getCreationEvent().setSource(theCase);
    712             Annotationtype.LATERALITY.copyAnnotationValues(dc, theCase, noOrFutureSpecimen, true);
    713             Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, noOrFutureSpecimen, Values.getStringOrNull((String)jsonCase.get("biopsyType")));
    714             dc.saveItem(noOrFutureSpecimen);
    715             jsonMessages.add(noOrFutureType.getName() + " '" + noOrFutureSpecimen.getName() + "' created successfully.");
    716           }
    717          
    718           Date samplingDateTime = null;
    719           if (noOrFutureType == Subtype.NO_SPECIMEN)
    720           {
    721             Annotationtype.REASON_IF_NO_SPECIMEN.setAnnotationValue(dc, noOrFutureSpecimen, Values.getStringOrNull((String)jsonCase.get("reasonIfNoSpecimen")));
    722             samplingDateTime = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonCase.get("samplingDate"));
    723           }
    724           else if (noOrFutureType == Subtype.FUTURE_SPECIMEN)
    725           {
    726             Annotationtype.OTHER_PATH_NOTE.setAnnotationValue(dc, noOrFutureSpecimen, Values.getStringOrNull((String)jsonCase.get("otherPathNote")));
    727             samplingDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("samplingDate"));
    728             Date rnaLaterDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("rnaLaterDate"));
    729             Annotationtype.RNALATER_DATETIME.setAnnotationValue(dc, noOrFutureSpecimen, rnaLaterDateTime);
    730           }
    731          
    732           Annotationtype.PAD.setAnnotationValue(dc, noOrFutureSpecimen, pad);
    733           Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, noOrFutureSpecimen, samplingDateTime);
    734           noOrFutureSpecimen.getCreationEvent().setEventDate(samplingDateTime);
    735           if (samplingDateTime != null)
    736           {
    737             refDate = refDate.getThisOrTheReplacement(new ReferenceDateWithSource(samplingDateTime, ReferenceDateSource.SAMPLING_DATE));
    738           }
     717            noSpecimen = Sample.getNew(dc);
     718            noSpecimen.setName(SpecimenTube.getNextSpecimenName(dc, originalCaseName));
     719            noSpecimen.setExternalId(SpecimenTube.getNextExternalId(dc, Subtype.NO_SPECIMEN));
     720            noSpecimen.setItemSubtype(Subtype.NO_SPECIMEN.load(dc));
     721            noSpecimen.getCreationEvent().setSource(theCase);
     722            Annotationtype.LATERALITY.copyAnnotationValues(dc, theCase, noSpecimen, true);
     723            dc.saveItem(noSpecimen);
     724            jsonMessages.add("NoSpecimen '" + noSpecimen.getName() + "' created successfully.");
     725          }
     726         
     727          noSpecimen.getCreationEvent().setEventDate(samplingDate);
     728          Annotationtype.PAD.setAnnotationValue(dc, noSpecimen, pad);
     729          Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, noSpecimen, samplingDate);
     730          Annotationtype.REASON_IF_NO_SPECIMEN.setAnnotationValue(dc, noSpecimen, Values.getString((String)jsonCase.get("reasonIfNoSpecimen")));
     731          Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, noSpecimen, Values.getStringOrNull((String)jsonCase.get("biopsyType")));
    739732        }
    740733       
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ReferenceDateServlet.java

    r6440 r6510  
    147147        caseQuery.order(Orders.asc(Hql.property("parent.id")));
    148148       
    149         // Load all child Specimen/NoSpecimen/FutureSpecimen with a known creation date
     149        // Load all child Specimen/NoSpecimen with a known creation date
    150150        // IMPORTANT!! Sort by oldest first
    151151        ItemQuery<Sample> specimenQuery = Sample.getQuery();
     
    154154          Restrictions.or(
    155155            Subtype.SPECIMEN.restriction(dc, null),
    156             Subtype.NO_SPECIMEN.restriction(dc, null),
    157             Subtype.FUTURE_SPECIMEN.restriction(dc, null)
     156            Subtype.NO_SPECIMEN.restriction(dc, null)
    158157          ));
    159158        specimenQuery.join(Hql.innerJoin(null, "parent", "c", null, true));
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/RetractionServlet.java

    r6329 r6510  
    8080import net.sf.basedb.reggie.dao.FlowCell;
    8181import net.sf.basedb.reggie.dao.FlowThrough;
    82 import net.sf.basedb.reggie.dao.FutureSpecimen;
    8382import net.sf.basedb.reggie.dao.Histology;
    8483import net.sf.basedb.reggie.dao.Library;
     
    245244    ItemSubtype specimenType = Subtype.SPECIMEN.get(dc);
    246245    ItemSubtype noSpecimenType = Subtype.NO_SPECIMEN.get(dc);
    247     ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);
    248246   
    249247    ItemSubtype histologyType = Subtype.HISTOLOGY.get(dc);
     
    269267    JSONArray jsonSpecimen = new JSONArray();
    270268    JSONArray jsonNoSpecimen = new JSONArray();
    271     JSONArray jsonFutureSpecimen = new JSONArray();
    272269   
    273270    JSONArray jsonHistology = new JSONArray();
     
    333330        loadNoSpecimenInfo(dc, ns);
    334331        jsonNoSpecimen.add(ns.asJSONObject());
    335       }
    336       else if (futureSpecimenType.equals(subtype))
    337       {
    338         FutureSpecimen fs = FutureSpecimen.getById(dc, itemId);
    339         loadFutureSpecimenInfo(dc, fs);
    340         jsonFutureSpecimen.add(fs.asJSONObject());
    341332      }
    342333      else if (histologyType.equals(subtype))
     
    428419    if (jsonSpecimen.size() > 0) json.put("specimen", jsonSpecimen);
    429420    if (jsonNoSpecimen.size() > 0) json.put("noSpecimen", jsonNoSpecimen);
    430     if (jsonFutureSpecimen.size() > 0) json.put("futureSpecimen", jsonFutureSpecimen);
    431421
    432422    if (jsonHistology.size() > 0) json.put("histology", jsonHistology);
     
    493483    ItemSubtype caseType = Subtype.CASE.get(dc);
    494484    Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc);
    495     ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);
    496485    ItemSubtype pooledLibraryType = Subtype.POOLED_LIBRARY.get(dc);
    497486   
     
    535524      {
    536525        comment = "To be replaced by a copy with the same name";
    537       }
    538       else if (futureSpecimenType.equals(subtype))
    539       {
    540         comment = "We must wait for information and samples from external lab";
    541         hasDeletePermission = false;
    542526      }
    543527      else if (pooledLibraryType.equals(subtype))
     
    759743  }
    760744
    761   private void loadFutureSpecimenInfo(DbControl dc, FutureSpecimen specimen)
    762   {
    763     Sample s = specimen.getSample();
    764     specimen.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
    765     specimen.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
    766     specimen.setAnnotation("editable", s.hasPermission(Permission.WRITE));
    767    
    768     specimen.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
    769     specimen.loadAnnotations(dc, "pad", Annotationtype.PAD, null);
    770     specimen.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME,  Reggie.CONVERTER_DATETIME_TO_STRING);
    771     specimen.setAnnotation("comment", s.getDescription());
    772   }
    773  
    774745  private void loadNoSpecimenInfo(DbControl dc, NoSpecimen noSpecimen)
    775746  {
     
    13831354        ItemSubtype caseType = Subtype.CASE.get(dc);
    13841355        ItemSubtype bloodType = Subtype.BLOOD.get(dc);
    1385         ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);
    13861356        Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc);
    13871357
     
    14611431                  itemName + " (" + subtype.getName() + ") is not registered as destroyed");
    14621432            }
    1463           }
    1464          
    1465           if (futureSpecimenType.equals(subtype))
    1466           {
    1467             throw new PermissionDeniedException(Permission.DELETE,
    1468               itemName + ": FutureSpecimen must wait for information from external lab");
    14691433          }
    14701434         
Note: See TracChangeset for help on using the changeset viewer.