Changeset 6510
- Timestamp:
- Dec 3, 2021, 9:24:38 AM (8 months ago)
- Location:
- extensions/net.sf.basedb.reggie/trunk
- Files:
-
- 3 deleted
- 42 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
extensions/net.sf.basedb.reggie/trunk
- Property svn:mergeinfo changed
/extensions/net.sf.basedb.reggie/branches/4.33-stable (added) merged: 6480-6508 /extensions/net.sf.basedb.reggie/tags/4.33.5 (added) merged: 6509
- Property svn:mergeinfo changed
-
extensions/net.sf.basedb.reggie/trunk/META-INF/servlets.xml
r6179 r6510 186 186 </servlet> 187 187 <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> 190 190 </servlet> 191 191 <servlet> -
extensions/net.sf.basedb.reggie/trunk/resources/batch/import-external-specimen.js
r6474 r6510 29 29 30 30 Wizard.showLoadingAnimation('Loading items...'); 31 var url = '../ FutureSpecimen.servlet?ID='+App.getSessionId();31 var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId(); 32 32 url += '&cmd=GetImportInformation'; 33 33 Wizard.asyncJsonRequest(url, specimen.initializeStep1); … … 51 51 52 52 html += '<tr>'; 53 html += '<th>Type</th>';54 53 html += '<th class="dottedleft">Item</th>'; 54 html += '<th class="dottedleft">Case</th>'; 55 55 html += '<th class="dottedleft">JSON file</th>' 56 56 html += '<th>Date</th>'; … … 78 78 79 79 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>'; 82 101 html += '<td class="dottedleft" style="white-space: nowrap;">'; 83 102 if (jsonFile) … … 137 156 if (jsonFile && jsonFile.warnings) 138 157 { 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+'">'; 140 160 for (var warnNo = 0; warnNo < jsonFile.warnings.length; warnNo++) 141 161 { … … 144 164 html += '</ol></div>'; 145 165 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 } 146 170 } 147 171 if (canImport && startNo == 1) … … 163 187 } 164 188 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 166 201 Doc.show('step-1'); 167 202 Doc.show('gonext'); 168 203 } 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 } 169 212 170 213 specimen.downloadJsonFile = function(event) … … 173 216 var file = importItems[itemNo].jsonFile; 174 217 175 var url = '../ FutureSpecimen.servlet?ID='+App.getSessionId();218 var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId(); 176 219 url += '&cmd=DownloadJsonFile'; 177 220 url += '&file='+encodeURIComponent(file.name); … … 296 339 297 340 /** 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. 300 342 */ 301 343 specimen.sortByFileDate = function(a, b) … … 359 401 } 360 402 361 var url = '../ FutureSpecimen.servlet?ID='+App.getSessionId();403 var url = '../ExternalSpecimen.servlet?ID='+App.getSessionId(); 362 404 url += '&cmd=ImportFromJSON'; 363 405 -
extensions/net.sf.basedb.reggie/trunk/resources/batch/import-external-specimen.jsp
r6350 r6510 80 80 opacity: 0.5; 81 81 } 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 102 img.case-summary 103 { 104 margin-left: 0.25em; 105 } 82 106 </style> 83 107 </base:head> -
extensions/net.sf.basedb.reggie/trunk/resources/index.jsp
r6442 r6510 1080 1080 <li><span class="require-permission" data-role="PatientCurator" data-link="personal/persinfo.jsp?ID=<%=ID%>" 1081 1081 >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> 1082 1086 1083 1087 <li><span class="require-permission" data-role="PatientCurator" data-link="personal/bloodform.jsp?ID=<%=ID%>" … … 1135 1139 <li><span class="require-permission" data-role="Administrator" data-link="batch/import-external-specimen.jsp?ID=<%=ID%>" 1136 1140 >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" 1140 1142 title="Number JSON files waiting to be imported">∙</span> 1141 1143 -
extensions/net.sf.basedb.reggie/trunk/resources/personal/bloodform.js
r6277 r6510 10 10 11 11 var caseIsValid = false; 12 var pnrIsTested = false; 12 13 var pnrIsValid = false; 13 14 var pnrIsAcceptable = false; … … 98 99 frm.personalNumber.value = patientInfo.personalNumber; 99 100 blood.personalNumberOnChange(); 101 pnrIsValid = true; 100 102 Wizard.goNext(false); 101 103 } … … 107 109 var frm = document.forms['reggie']; 108 110 var pnr = frm.personalNumber.value; 111 109 112 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 110 123 pnrIsAcceptable = true; 111 112 var pnrLen = pnr.length;113 124 if (pnrLen != 12 && pnrLen != 10) 114 125 { … … 158 169 blood.validateStep1 = function(event) 159 170 { 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 { 170 176 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 } 176 186 } 177 187 } -
extensions/net.sf.basedb.reggie/trunk/resources/personal/persinfo.js
r6239 r6510 8 8 var bloodInfo = null; 9 9 10 var pnrIsTested = false; 10 11 var pnrIsValid = false; 11 12 var pnrIsAcceptable = false; … … 26 27 Events.addEventHandler('personalNumber', 'keyup', persinfo.personalNumberOnChange); 27 28 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); 28 32 29 33 // Step 2 … … 38 42 Events.addEventHandler('step-3', 'wizard-validate', persinfo.validateStep3); 39 43 Events.addEventHandler('pad', 'blur', persinfo.padOnChange); 40 Events.addEventHandler('newNoSpecimen', 'click', persinfo.newSpecimenTypeOnChange);41 Events.addEventHandler('newFutureSpecimen', 'click', persinfo.newSpecimenTypeOnChange);42 44 Events.addEventHandler('samplingDate', 'blur', persinfo.samplingDateTimeOnChange); 43 45 Events.addEventHandler('samplingTime', 'blur', persinfo.samplingDateTimeOnChange); … … 60 62 Doc.show('step-1'); 61 63 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 63 123 64 124 persinfo.caseNameOnChange = function() … … 67 127 var caseName = frm.caseName.value.toUpperCase(); 68 128 caseIsValid = false; 129 Doc.element('numSpecimenTubes').innerHTML = ''; 69 130 if (caseName == '') 70 131 { … … 97 158 caseInfo = response.caseInfo; 98 159 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>'; 99 162 100 163 if (caseInfo && caseInfo.patient) … … 102 165 frm.personalNumber.value = caseInfo.patient.personalNumber; 103 166 persinfo.personalNumberOnChange(); 167 pnrIsValid = true; 104 168 Wizard.goNext(false); 105 169 } … … 108 172 frm.personalNumber.value = bloodInfo.patient.personalNumber; 109 173 persinfo.personalNumberOnChange(); 174 pnrIsValid = true; 110 175 Wizard.goNext(false); 111 176 } … … 117 182 var pnr = frm.personalNumber.value; 118 183 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 119 194 pnrIsAcceptable = true; 120 121 var pnrLen = pnr.length;122 195 if (pnrLen != 12 && pnrLen != 10) 123 196 { … … 167 240 persinfo.validateStep1 = function(event) 168 241 { 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 { 179 247 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 } 185 257 } 186 258 } … … 332 404 if (hasSpecimen) 333 405 { 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 343 408 for (var i = 0; i < caseInfo.specimen.length; i++) 344 409 { 345 410 var specimen = caseInfo.specimen[i]; 346 411 var isYellow = specimen.YellowLabel != null; 347 var isPaused = specimen.bioWell.bioPlate.name.indexOf('PSp') == 0;348 412 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 352 421 if (specimen.pad && !hasPAD) 353 422 { … … 365 434 if (specimen.laterality) 366 435 { 367 specimenTubes += Strings.encodeTags(specimen.laterality);368 436 Forms.checkRadio(frm.laterality, specimen.laterality); 369 437 if (specimen.laterality == 'LEFT') hasLeftSpecimen = true; … … 374 442 { 375 443 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 } 393 445 } 394 446 … … 400 452 if (numLateralities > 1) 401 453 { 402 Wizard.setInputStatus(' specimenTubes', 'warning', 'Specimen tubes with different laterality');454 Wizard.setInputStatus('laterality', 'warning', 'Specimen tubes with different laterality'); 403 455 thisCaseLaterality = null; 404 456 } … … 406 458 Doc.show('samplingDateSection'); 407 459 Doc.show('rnaLaterDateSection'); 408 460 Doc.show('specimenTubes'); 409 461 } 410 462 else … … 416 468 thisCaseSamplingDate = caseInfo.noSpecimen.samplingDate; 417 469 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'); 423 472 Doc.element('existingItemName').innerHTML = Strings.encodeTags(caseInfo.noSpecimen.name); 424 473 Doc.show('existingItemNameSection'); 425 474 } 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 }439 475 else 440 476 { 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'); 446 484 } 447 485 … … 524 562 if (!updateMode || cc.id == caseInfo.id) 525 563 { 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+'"'; 527 565 if (cc.laterality == thisCaseLaterality) cases += ' checked'; 528 566 cases += '>'; … … 627 665 } 628 666 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; 656 747 } 657 748 … … 669 760 { 670 761 var spId = Data.get(event.currentTarget, 'specimen-id'); 671 var index = Data.get(event.currentTarget, 'index');672 762 Doc.addOrRemoveClass('specimen-row.'+spId, 'yellow', event.currentTarget.checked); 673 caseInfo.specimen[index].YellowLabel = event.currentTarget.checked ? 'yellow' : null;674 763 } 675 764 … … 916 1005 917 1006 caseInfo.laterality = Forms.getCheckedRadio(frm.laterality).value; 918 caseInfo.newSpecimenType = frm.newSpecimenType.value;919 1007 caseInfo.reasonIfNoSpecimen = frm.reasonIfNoSpecimen.value; 920 caseInfo.otherPathNote = frm.otherPathNote.value;921 1008 caseInfo.pad = frm.pad.value; 922 1009 … … 941 1028 { 942 1029 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 } 943 1043 } 944 1044 -
extensions/net.sf.basedb.reggie/trunk/resources/personal/persinfo.jsp
r6349 r6510 30 30 > 31 31 <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) 45 33 { 46 34 background-color: #FFFFC0; 47 }48 .id-col, .laterality-col49 {50 text-align: left;51 }52 .yellow-col53 {54 text-align: center;55 }56 .paused .yellow-col57 {58 background-image: url('../images/pause.png');59 background-repeat: no-repeat;60 background-position: 100% 50%;61 35 } 62 36 </style> … … 66 40 <p:path><p:pathelement 67 41 title="Reggie" href="<%="../index.jsp?ID="+ID%>" 68 /><p:pathelement title="P ersonal informationregistration"42 /><p:pathelement title="Pathology referral form registration" 69 43 /></p:path> 70 44 … … 79 53 80 54 <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> 81 68 <tr> 82 69 <td class="prompt">Case name</td> … … 85 72 class="required auto-init" data-auto-init="focus" data-next-focus="personalNumber" 86 73 style="width: 12em;" maxlength="12"> 74 <span id="numSpecimenTubes"></span> 87 75 </td> 88 76 <td class="status" id="caseName.status"></td> … … 214 202 </td> 215 203 </tr> 216 <tr >204 <tr id="noSpecimenSection" style="display: none;"> 217 205 <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> 234 209 </tr> 235 210 <tr id="existingItemNameSection" style="display: none;"> … … 239 214 <td class="help"></td> 240 215 </tr> 241 <tr id="samplingDateSection" >216 <tr id="samplingDateSection" style="display: none;"> 242 217 <td class="subprompt">Sampling date</td> 243 218 <td class="input"> … … 253 228 </td> 254 229 </tr> 255 <tr id="rnaLaterDateSection" >230 <tr id="rnaLaterDateSection" style="display: none;"> 256 231 <td class="subprompt">RNA Later date</td> 257 232 <td class="input"> … … 268 243 </td> 269 244 </tr> 270 <tr id="reasonIfNoSpecimenSection" class="align-top" >245 <tr id="reasonIfNoSpecimenSection" class="align-top" style="display: none;"> 271 246 <td class="subprompt">Reason if no specimen</td> 272 247 <td class="input"> … … 277 252 <td class="help">Comment why there was no specimen tubes in the delivery.</td> 278 253 </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> 287 255 </table> 288 256 </div> -
extensions/net.sf.basedb.reggie/trunk/resources/personal/retraction_followup_form.js
r6159 r6510 249 249 var html = ''; 250 250 html += rf.tableRowsForItems('Specimen', response.specimen, 'SAMPLE'); 251 html += rf.tableRowsForItems('FutureSpecimen', response.futureSpecimen, 'SAMPLE', true);252 251 html += rf.tableRowsForItems('Lysate', response.lysate, 'EXTRACT'); 253 252 html += rf.tableRowsForItems('RNA', response.rna, 'EXTRACT'); … … 273 272 } 274 273 275 if (response.futureSpecimen)276 {277 Wizard.setInputStatus('itemList', 'warning', 'FutureSpecimen exists! We need to wait for more information from the external lab.');278 }279 274 } 280 275 else -
extensions/net.sf.basedb.reggie/trunk/resources/personal/retractionform.js
r6155 r6510 385 385 var specimen = response.specimen; 386 386 var noSpecimen = response.noSpecimen; 387 var futureSpecimen = response.futureSpecimen;388 387 var histology = response.histology; 389 388 var stained = response.stained; … … 433 432 } 434 433 if (noSpecimen && noSpecimen.length > 0) 435 {436 itemExists = true;437 }438 if (futureSpecimen && futureSpecimen.length > 0)439 434 { 440 435 itemExists = true; … … 513 508 html += htmlTableRowsForItems(specimen, 'Specimen', 'specimen', 'Sampling', 'PAD', 'Storage box', false, false); 514 509 html += htmlTableRowsForItems(noSpecimen, 'NoSpecimen', 'nospecimen', 'Sampling', 'PAD', 'NA', false, false); 515 html += htmlTableRowsForItems(futureSpecimen, 'FutureSpecimen', 'futurespecimen', 'Sampling', 'PAD', 'NA', false, false);516 510 html += htmlTableRowsForItems(histology, 'Histology', 'histology', 'Partition', null, 'Paraffin block', true, true); 517 511 html += htmlTableRowsForItems(stained, 'Stained', 'stained', null, null, 'Slide', false, false); -
extensions/net.sf.basedb.reggie/trunk/resources/reports/case-summary.js
r6479 r6510 203 203 var specimen = response.specimen; 204 204 var noSpecimen = response.noSpecimen; 205 var futureSpecimen = response.futureSpecimen;206 205 var numSpecimenOfAnyType = 0; 207 206 var yellowPrefixes = {}; … … 266 265 defaultColClass = null; 267 266 } 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 try276 {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 }296 267 297 268 if (numSpecimenOfAnyType == 0) … … 300 271 Doc.hide('specimen-details'); 301 272 Doc.hide('nospecimen-info'); 302 Doc.hide('futurespecimen-info');303 273 } 304 274 else … … 310 280 } 311 281 if (!noSpecimen || noSpecimen.length == 0) Doc.hide('nospecimen-info'); 312 if (!futureSpecimen || futureSpecimen.length == 0) Doc.hide('futurespecimen-info');313 282 } 314 283 -
extensions/net.sf.basedb.reggie/trunk/resources/reports/case_summary.jsp
r6479 r6510 326 326 </div> 327 327 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 366 328 <div class="info-section bg-filled-100" id="histology-info"> 367 329 <div> -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/counter/CounterService.java
r6387 r6510 416 416 json.put("specimen-all", query.count(dc)); 417 417 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 418 442 // Specimen tubes to be partitioned 419 443 query = Sample.getQuery(); … … 488 512 query.setCacheResult(true); 489 513 json.put("case-or-blood-without-consent", query.count(dc)); 490 491 // FutureSpecimen492 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));497 514 } 498 515 -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Annotationtype.java
r6476 r6510 588 588 589 589 /** 590 The "QiacubeRunNo" annotation type, used for extracts (RNA, DNA ).590 The "QiacubeRunNo" annotation type, used for extracts (RNA, DNA, FlowThrough). 591 591 It is an integer annotation type with allowed values >= 1. 592 592 @since 2.6 … … 595 595 new Annotationtype("QiacubeRunNo", Type.INT, false, Item.EXTRACT); 596 596 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 597 607 /** 598 608 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 67 67 { 68 68 // 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) 70 70 merged = true; 71 71 caseQuery = Sample.getQuery(); … … 75 75 caseQuery.join(Hql.innerJoin("evt", "bioMaterial", "sp")); // 'sp' should now reference a specimen tube 76 76 77 // Restrict to 'Specimen' ,'NoSpecimen' or 'FutureSpecimen' child items78 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"))); 79 79 caseQuery.restrict(Restrictions.like(Hql.property("sp", "name"), Expressions.parameter("name", name + ".%", Type.STRING))); 80 80 caseQuery.setDistinct(true); … … 162 162 /** 163 163 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. 166 166 The case numbers are returned as strings sorted in numerical order. 167 167 @since 2.12 … … 179 179 180 180 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))); 182 182 query.restrict(Restrictions.eq(Hql.property("parent.parent"), Hql.entity(patient.getBioSource()))); 183 183 for (Sample spec : query.list(dc)) -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/SpecimenTube.java
r6193 r6510 272 272 query.restrict(Restrictions.or( 273 273 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) 276 275 )); 277 276 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 92 92 public static final Subtype NO_SPECIMEN = new Subtype("NoSpecimen", null, null, "S", Item.SAMPLE, false); 93 93 94 /**95 The definition of the "FutureSpecimen" subtype (for cases when a specimen is expected but has not yet96 been received).97 @since 4.3298 */99 public static final Subtype FUTURE_SPECIMEN = new Subtype("FutureSpecimen", null, null, "S", Item.SAMPLE, false);100 101 102 94 /** 103 95 The definition of the "TMASpecimen" subtype. -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/DateValidator.java
r6343 r6510 102 102 { 103 103 Date result = null; 104 try104 if (value != null) 105 105 { 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 115 107 { 116 section.addWarningMessage("Future date in JSON: "+entryKey+"="+value+" (parsed as '"+result+"'");108 result = dateFormat.parse(value); 117 109 } 118 if (notBefore != null && result.before(notBefore))110 catch (Exception ex) 119 111 { 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 } 122 125 } 123 126 } -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/DnaInfo.java
r6344 r6510 19 19 public Integer qiacubePos; 20 20 public Integer qiacubeRunNumber; 21 public String qiacubeRunId; 21 22 public String operator; 22 23 public Float qubitConc; … … 25 26 public boolean valid; 26 27 27 public DnaInfo(JsonSection section )28 public DnaInfo(JsonSection section, RnaInfo rna) 28 29 { 29 30 if (section != null) … … 34 35 operator = section.getOptionalEntry("Qiacube operator", null); 35 36 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 38 51 qubitConc = section.getRequiredEntry("Concentration (ng/ul)", FloatValidator.POSITIVE); 39 // TODO -- protocol40 52 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)); 41 58 } 42 59 valid = section != null && !section.hasError(); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FastqInfo.java
r6474 r6510 38 38 { 39 39 //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)); 41 41 } 42 42 if (R2 != null) 43 43 { 44 44 //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)); 46 46 } 47 47 } -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FloatValidator.java
r6205 r6510 22 22 public static final FloatValidator POSITIVE = new FloatValidator(0f, null); 23 23 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 24 30 private Float maxValue; 25 31 private Float minValue; -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/FlowThroughInfo.java
r6221 r6510 19 19 public Integer qiacubePos; 20 20 public Integer qiacubeRunNumber; 21 public String qiacubeRunId; 21 22 public String operator; 22 23 … … 24 25 public boolean valid; 25 26 26 public FlowThroughInfo(JsonSection section )27 public FlowThroughInfo(JsonSection section, RnaInfo rna) 27 28 { 28 29 if (section != null) … … 33 34 operator = section.getOptionalEntry("Qiacube operator", null); 34 35 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 38 49 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)); 39 55 } 40 56 valid = section != null && !section.hasError(); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/JsonFile.java
r6474 r6510 277 277 specimenInfo = new SpecimenInfo(getRequiredSection("Specimen"), mainInfo); 278 278 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); 282 282 } 283 libInfo = new LibraryInfo(getRequiredSection("Library"), ctx);283 libInfo = new LibraryInfo(getRequiredSection("Library"), mainInfo, ctx); 284 284 poolInfo = new PoolInfo(getRequiredSection("Pool"), libInfo, ctx); 285 285 flowCellInfo = new FlowCellInfo(getRequiredSection("FlowCell"), poolInfo); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/JsonSection.java
r6457 r6510 89 89 Get an optional entry from the JSON file. A validator is 90 90 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. 92 92 */ 93 93 @SuppressWarnings("unchecked") … … 95 95 { 96 96 T result = null; 97 if (json.containsKey(key)) 97 Object val = json.get(key); 98 if (validator != null) 98 99 { 99 Object val = json.get(key); 100 if (validator != null) 100 if (val != null && !validator.getExpectedClass().isInstance(val)) 101 101 { 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()+")"); 118 104 } 119 105 else 120 106 { 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 } 122 115 } 116 } 117 else 118 { 119 result = (T)val; 123 120 } 124 121 return result; -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LibraryInfo.java
r6474 r6510 22 22 import net.sf.basedb.reggie.dao.Pipeline; 23 23 import net.sf.basedb.reggie.dao.Subtype; 24 import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef.SampleIdType; 24 25 import net.sf.basedb.util.Coordinate; 25 26 … … 51 52 public boolean valid; 52 53 53 public LibraryInfo(JsonSection section, ImportContext ctx)54 public LibraryInfo(JsonSection section, MainInfo main, ImportContext ctx) 54 55 { 55 56 if (section != null) … … 89 90 barcode = section.getRequiredEntry("Barcode", BarcodeValidator.INSTANCE); 90 91 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 } 91 99 } 92 100 valid = section != null && !section.hasError(); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LongValidator.java
r6474 r6510 17 17 Allow all long values. 18 18 */ 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(); 26 20 27 21 /** 28 22 All positive values > 0. 29 23 */ 30 public static final LongValidator POSITIVE = new LongValidator(1l, null , false);24 public static final LongValidator POSITIVE = new LongValidator(1l, null); 31 25 32 /**33 All positive values > 0 or null.34 @since 4.33.435 */36 public static final LongValidator POSITIVE_OR_NULL = new LongValidator(1l, null, true);37 38 private boolean allowNull;39 26 private Long maxValue; 40 27 private Long minValue; … … 46 33 Allow all long values. 47 34 */ 48 public LongValidator(boolean allowNull) 49 { 50 this.allowNull = allowNull; 51 } 35 public LongValidator() 36 {} 52 37 53 38 /** … … 55 40 Null values are allowed and mean no limit. 56 41 */ 57 public LongValidator(Long min, Long max , boolean allowNull)42 public LongValidator(Long min, Long max) 58 43 { 59 44 this.minValue = min; 60 45 this.maxValue = max; 61 this.allowNull = allowNull;62 46 } 63 47 … … 101 85 { 102 86 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) 111 88 { 112 89 result = ((Number)value).longValue(); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/LysateInfo.java
r6221 r6510 32 32 originalVolume = section.getRequiredEntry("Original volume (ul)", FloatValidator.POSITIVE); 33 33 usedFromSpecimen = section.getRequiredEntry("Used quantity (mg)", FloatValidator.POSITIVE); 34 // TODO -- protocol35 34 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)); 36 41 37 42 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 18 18 { 19 19 /** 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. 21 22 */ 22 23 public static final PatternValidator CMD_ID = new PatternValidator("[0-9]+[0-9\\-]+", "ID", "cmd:$0", null); 23 24 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 24 35 /** 25 36 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 24 24 Validator for plates with 8 rows and 12 columns. 25 25 */ 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); 27 27 28 28 /** … … 30 30 @since 4.33.4 31 31 */ 32 public static final PlateWellValidator STRIP_1x8 = new PlateWellValidator(1, 8 );32 public static final PlateWellValidator STRIP_1x8 = new PlateWellValidator(1, 8, CoordinateSystem.NUMERIC); 33 33 34 34 /** 35 35 Validator fow Qiacube positions which are represented as 6 rows with 2 columns. 36 36 */ 37 public static final PlateWellValidator QIACUBE = new PlateWellValidator(6, 2 );37 public static final PlateWellValidator QIACUBE = new PlateWellValidator(6, 2, CoordinateSystem.NUMERIC_ALPHA); 38 38 39 private final Pattern a1b1Pattern;40 private final Pattern numericPattern;41 39 private final int maxRows; 42 40 private final int maxCols; 41 private final CoordinateSystem[] systems; 43 42 44 public PlateWellValidator(int maxRows, int maxCols )43 public PlateWellValidator(int maxRows, int maxCols, CoordinateSystem... systems) 45 44 { 46 this.a1b1Pattern = Pattern.compile("([A-Z]+)\\:(\\d+)");47 this.numericPattern = Pattern.compile("(\\d+)\\:(\\d+)");48 45 this.maxRows = maxRows; 49 46 this.maxCols = maxCols; 47 this.systems = systems; 50 48 } 51 49 … … 53 51 public PlateCoordinate isValid(DbControl dc, String value, JsonSection section, String entryKey) 54 52 { 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) 60 55 { 61 Matcher m Numeric = numericPattern.matcher(value);62 if ( !mNumeric.matches())56 Matcher m = cs.matcher(value); 57 if (m.matches()) 63 58 { 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; 66 85 } 67 row = Integer.parseInt(mNumeric.group(1));68 col = Integer.parseInt(mNumeric.group(2));69 useA1B1 = false;70 }71 else72 {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 else86 {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;95 86 } 96 87 97 return valid ? new PlateCoordinate(row-1, col-1) : null; 88 section.addErrorMessage("Invalid plate well in JSON: "+entryKey+"="+value); 89 return null; 98 90 } 99 91 … … 104 96 } 105 97 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 } 106 155 } -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/ProtocolValidator.java
r6338 r6510 53 53 public Protocol isValid(DbControl dc, String externalRef, JsonSection section, String entryKey) 54 54 { 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); 57 56 if (externalRef == null) return null; 58 57 -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/RnaInfo.java
r6344 r6510 2 2 3 3 import java.util.Date; 4 import java.util.List; 5 6 import net.sf.basedb.core.DbControl; 7 import net.sf.basedb.core.Extract; 8 import net.sf.basedb.core.ItemQuery; 4 9 import net.sf.basedb.core.Protocol; 10 import net.sf.basedb.core.Type; 5 11 import net.sf.basedb.core.data.PlateCoordinate; 12 import net.sf.basedb.core.query.Annotations; 13 import net.sf.basedb.core.query.Expressions; 14 import net.sf.basedb.core.query.Hql; 15 import net.sf.basedb.core.query.Restrictions; 16 import net.sf.basedb.reggie.Reggie; 17 import net.sf.basedb.reggie.dao.Annotationtype; 18 import net.sf.basedb.reggie.dao.Subtype; 19 import net.sf.basedb.util.Coordinate; 6 20 7 21 /** … … 18 32 public Date qiacubeDate; 19 33 public Integer qiacubePos; 34 public String qiacubeRunId; 20 35 public Integer qiacubeRunNumber; 21 36 public String operator; 22 public Float rin OrRqs;37 public Float rin; 23 38 public Float qubitConc; 24 39 … … 26 41 public boolean valid; 27 42 28 public RnaInfo(JsonSection section )43 public RnaInfo(JsonSection section, ImportContext ctx) 29 44 { 30 45 if (section != null) … … 35 50 operator = section.getOptionalEntry("Qiacube operator", null); 36 51 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 39 69 qubitConc = section.getRequiredEntry("Concentration (ng/ul)", FloatValidator.POSITIVE); 40 // TODO -- RNAQC 41 // TODO -- protocol 70 rin = section.getRequiredEntry("RIN", FloatValidator.RIN); 42 71 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)); 43 78 } 44 79 valid = section != null && !section.hasError(); 45 80 } 46 81 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 } 47 126 } -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/ScanBIdRef.java
r6351 r6510 2 2 3 3 import net.sf.basedb.core.DbControl; 4 import net.sf.basedb.core.PermissionDeniedException; 5 import net.sf.basedb.reggie.dao.Case; 4 6 import net.sf.basedb.reggie.dao.Rna; 5 7 import net.sf.basedb.reggie.dao.SpecimenTube; … … 12 14 and it shoult not have existing child items. 13 15 * Specimen: An existing specimen with the exact name should already exist. 14 * Case: TODO -- Either an existing FutureSpecimen or an existing Case16 * Case: A new specimen is created for the given case. The case may or may not already exist. 15 17 16 18 @since 4.32 … … 24 26 public Rna rna; 25 27 public SpecimenTube specimen; 28 public Case theCase; 26 29 27 30 public ScanBIdRef() … … 43 46 id = value; 44 47 45 if (value.matches("\\d{7} "))48 if (value.matches("\\d{7}(C|D)?")) 46 49 { 47 // 7 digits is a SCAN-B CASE ID 50 // 7 digits is a SCAN-B CASE ID with optional 'C' or 'D' suffix 48 51 idType = SampleIdType.CASE; 49 // TODO -- load Case or FutureSpecimen50 52 } 51 53 else if (value.matches("\\d{7}\\.\\d")) … … 81 83 section.addErrorMessage("Invalid SCANB_ID: " + id); 82 84 } 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 } 83 102 } 84 103 return this; -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/SpecimenInfo.java
r6458 r6510 17 17 { 18 18 public String pad; 19 public String clarityId; 19 20 20 21 public Date arrivalDate; … … 42 43 if (main.idRef != null && main.idRef.idType == SampleIdType.CASE) 43 44 { 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)); 45 48 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); 49 72 } 50 73 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)); 54 76 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 67 81 // TODO -- check agains existing specimen and warn if values differ? 68 69 82 if (originalQuantity != null && remainingQuantity != null && remainingQuantity+0.1 > originalQuantity) 70 83 { -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/BloodFollowUpRegistrationServlet.java
r6329 r6510 404 404 Restrictions.or( 405 405 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) 408 407 )); 409 408 sampleQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/CaseSummaryServlet.java
r6479 r6510 58 58 import net.sf.basedb.reggie.dao.FlowCell; 59 59 import net.sf.basedb.reggie.dao.FlowThrough; 60 import net.sf.basedb.reggie.dao.FutureSpecimen;61 60 import net.sf.basedb.reggie.dao.GenotypeCall; 62 61 import net.sf.basedb.reggie.dao.Histology; … … 307 306 } 308 307 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 322 308 List<Histology> histology = Histology.findByCaseName(dc, caseName); 323 309 if (histology.size() > 0) … … 768 754 } 769 755 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 784 756 private void loadGenotypeCallInfo(DbControl dc, GenotypeCall gtc) 785 757 { -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ExportServlet.java
r6474 r6510 166 166 Restrictions.or( 167 167 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) 170 169 )); 171 170 } … … 179 178 Subtype.SPECIMEN.restriction(dc, null), 180 179 Subtype.NO_SPECIMEN.restriction(dc, null), 181 Subtype.FUTURE_SPECIMEN.restriction(dc, null),182 180 Subtype.BLOOD.restriction(dc, null) 183 181 )); … … 251 249 ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc); 252 250 ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc); 253 ItemSubtype subtypeFutureSpecimen = Subtype.FUTURE_SPECIMEN.load(dc);254 251 ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc); 255 252 … … 276 273 consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, manager, s); 277 274 } 278 else if (subtypeSpecimen.equals(sampleType) || subtypeNoSpecimen.equals(sampleType) || subtypeFutureSpecimen.equals(sampleType))275 else if (subtypeSpecimen.equals(sampleType) || subtypeNoSpecimen.equals(sampleType)) 279 276 { 280 277 // The parent is the 'Case' and the grandparent is the 'Patient' for specimens and no specimens … … 752 749 ItemSubtype subtypeSpecimen = Subtype.SPECIMEN.load(dc); 753 750 ItemSubtype subtypeNoSpecimen = Subtype.NO_SPECIMEN.load(dc); 754 ItemSubtype subtypeFutureSpecimen = Subtype.FUTURE_SPECIMEN.load(dc);755 751 ItemSubtype subtypeBlood = Subtype.BLOOD.load(dc); 756 752 … … 783 779 sampleType.equals("specimen_nospecimen")) 784 780 { 785 // Include 'Specimen' , 'No specimen' and 'FutureSpecimen' items781 // Include 'Specimen' and 'No specimen' items 786 782 sampleQuery.restrict( 787 783 Restrictions.or( 788 784 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) 791 786 )); 792 787 sampleQuery.join(Hql.innerJoin(null, "parent", "cse", true)); … … 868 863 if (biopsyType == null) 869 864 { 870 if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype) || subtypeFutureSpecimen.equals(sampleSubtype))865 if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype)) 871 866 { 872 867 biopsyType = "default"; … … 898 893 patient = s.getParent(); 899 894 } 900 else if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype) || subtypeFutureSpecimen.equals(sampleSubtype))895 else if (subtypeSpecimen.equals(sampleSubtype) || subtypeNoSpecimen.equals(sampleSubtype)) 901 896 { 902 897 // The grandparent is the 'Patient' for specimens and no specimens … … 917 912 } 918 913 } 919 if (sampleSubtype.equals(subtypeSpecimen) || sampleSubtype.equals(subtypeFutureSpecimen))914 if (sampleSubtype.equals(subtypeSpecimen)) 920 915 { 921 916 // Get PAD reference … … 1273 1268 "\t" + patientAllFirstNames + 1274 1269 "\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"))) 1276 1271 { 1277 1272 returnStr += "\t" + padReference + … … 1608 1603 Restrictions.or( 1609 1604 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) 1612 1606 )); 1613 1607 specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); … … 1770 1764 1771 1765 /** 1772 Get the external (release) ID for all specimen , no-specimen or future-specimen1766 Get the external (release) ID for all specimen or no-specimen 1773 1767 related to the patient. 1774 1768 */ … … 1789 1783 Restrictions.or( 1790 1784 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) 1793 1786 )); 1794 1787 specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); … … 1886 1879 Restrictions.or( 1887 1880 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) 1890 1882 )); 1891 1883 specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ImportServlet.java
r6336 r6510 136 136 findByPAD.join(Hql.innerJoin("cce", "event", "evt")); 137 137 findByPAD.join(Hql.innerJoin("evt", "bioMaterial", "sp")); // 'sp' should now reference a specimen tube/nospecimen 138 // Restrict to 'Specimen' , 'NoSpecimen' or 'FutureSpecimen' child items139 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"))); 140 140 141 141 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 281 281 jsonChecks.add(checkSubtype(dc, Subtype.SPECIMEN,null, createIfMissing, Subtype.CASE)); 282 282 jsonChecks.add(checkSubtype(dc, Subtype.NO_SPECIMEN,null, createIfMissing, Subtype.CASE)); 283 jsonChecks.add(checkSubtype(dc, Subtype.FUTURE_SPECIMEN,null, createIfMissing, Subtype.CASE));284 283 jsonChecks.add(checkSubtype(dc, Subtype.TMA_SPECIMEN,null, createIfMissing, Subtype.CASE)); 285 284 jsonChecks.add(checkSubtype(dc, Subtype.HISTOLOGY_PROTOCOL, null, createIfMissing)); … … 505 504 jsonChecks.add(checkAnnotationType(dc, Annotationtype.QIACUBE_POSITION, 1, new ValueOptions(1, 12), createIfMissing, effectivePermissionsUse)); 506 505 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)); 507 507 508 508 jsonChecks.add(checkAnnotationType(dc, Annotationtype.QC_RUN_DATE, 1, null, createIfMissing, effectivePermissionsUse)); … … 881 881 Annotationtype.PAD, Annotationtype.RNALATER_DATETIME, 882 882 Annotationtype.SAMPLING_DATETIME, Annotationtype.SPECIMEN_TYPE, 883 Annotationtype.EXTERNAL_REF, 883 884 Annotationtype.LINKED_SPECIMEN, Annotationtype.YELLOW_LABEL, 884 885 Annotationtype.COMPLETED_DATE, … … 893 894 )); 894 895 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_PROCESSING903 ));904 905 896 jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.TMA_SPECIMEN, createIfMissing, 906 897 Annotationtype.TMA_BLOCK, Annotationtype.TMA_BLOCK_POS, … … 937 928 jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.RNA, createIfMissing, 938 929 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, 940 931 Annotationtype.ND_CONC, Annotationtype.ND_260_BY_280, Annotationtype.ND_260_BY_230, 941 932 Annotationtype.QUBIT_CONC, … … 961 952 jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.DNA, createIfMissing, 962 953 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, 964 955 Annotationtype.ND_CONC, Annotationtype.ND_260_BY_280, Annotationtype.ND_260_BY_230, 965 956 Annotationtype.QUBIT_CONC, … … 991 982 jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.FLOW_THROUGH, createIfMissing, 992 983 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, 994 985 Annotationtype.ALLPREP_MINI_KIT, Annotationtype.ETOH70, 995 986 Annotationtype.BUFFER_RW1, Annotationtype.BUFFER_RPE, -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/LinkedSpecimenServlet.java
r6336 r6510 120 120 121 121 // Load all patients and cases that have at least one 122 // specimen/nospecimen /futurespecimenwithout creation date122 // specimen/nospecimen without creation date 123 123 ItemQuery<Sample> queryNoDate = Sample.getQuery(); 124 124 queryNoDate.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); … … 126 126 Restrictions.or( 127 127 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) 130 129 )); 131 130 queryNoDate.join(Hql.innerJoin(null, "parent", "c", null, true)); … … 136 135 queryNoDate.restrict(Restrictions.eq(Hql.property("ce", "eventDate"), null)); 137 136 138 // Load all specimen/nospecimen /futurespecimenwith a known creation date137 // Load all specimen/nospecimen with a known creation date 139 138 // IMPORTANT!! Sort by oldest first 140 139 ItemQuery<Sample> queryHasDate = Sample.getQuery(); … … 143 142 Restrictions.or( 144 143 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) 147 145 )); 148 146 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 33 33 import net.sf.basedb.core.query.Expressions; 34 34 import net.sf.basedb.core.query.Hql; 35 import net.sf.basedb.core.query.Orders; 35 36 import net.sf.basedb.core.query.Restrictions; 36 37 import net.sf.basedb.reggie.JsonUtil; … … 44 45 import net.sf.basedb.reggie.dao.Case; 45 46 import net.sf.basedb.reggie.dao.Consent; 46 import net.sf.basedb.reggie.dao.FutureSpecimen;47 47 import net.sf.basedb.reggie.dao.NoSpecimen; 48 48 import net.sf.basedb.reggie.dao.Patient; … … 94 94 json.put("count", count); 95 95 } 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 } 96 143 else if ("GetCaseInfo".equals(cmd)) 97 144 { … … 118 165 List<SpecimenTube> specimenTubes = null; 119 166 NoSpecimen noSpecimen = null; 120 FutureSpecimen futureSpecimen = null;121 167 JSONObject jsonCase = null; 122 168 JSONObject jsonBlood = null; … … 149 195 { 150 196 noSpecimen = nsList.get(0); 151 }152 153 if (noSpecimen == null)154 {155 // Also check if there are any 'FutureSpecimen' items156 List<FutureSpecimen> fsList = FutureSpecimen.findByCase(dc, theCase, caseName, site.useCaseSuffixForPreNeoForms());157 if (fsList.size() > 1)158 {159 // There should be at most one 'NoSpecimen' item160 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 }168 197 } 169 198 } … … 256 285 tube.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING); 257 286 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); 258 291 jsonTubes.add(tube.asJSONObject()); 259 292 } … … 267 300 noSpecimen.loadAnnotations(dc, "reasonIfNoSpecimen", Annotationtype.REASON_IF_NO_SPECIMEN, null); 268 301 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());278 302 } 279 303 … … 505 529 if (samplingDateTime != null) Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, specimen, samplingDateTime); 506 530 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 507 536 String yellowLabel = (String)jsonSpec.get("YellowLabel"); 508 537 String yellowLabelOriginal = (String)jsonSpec.get("YellowLabelOriginal"); … … 520 549 else 521 550 { 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(); 531 565 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."); 565 575 } 566 576 … … 611 621 JSONArray jsonSpecimen = (JSONArray)jsonCase.get("specimen"); 612 622 JSONObject jsonNoSpecimen = (JSONObject)jsonCase.get("noSpecimen"); 613 JSONObject jsonFutureSpecimen = (JSONObject)jsonCase.get("futureSpecimen");614 623 615 624 Set<SharedItem> itemsToPublish = new HashSet<>(); … … 624 633 ItemQuery<Sample> childQuery = theCase.getChildSamples(); 625 634 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 num Children= 0;635 childQuery.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, null), Subtype.NO_SPECIMEN.restriction(dc, null))); 636 637 int numUpdated = 0; 629 638 for (Sample child : childQuery.list(dc)) 630 639 { 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 } 640 649 } 641 650 … … 647 656 Date samplingDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("samplingDate")); 648 657 Date rnaLaterDateTime = Reggie.CONVERTER_STRING_TO_DATETIME.convert((String)jsonCase.get("rnaLaterDate")); 658 String otherPathNote = (String)jsonCase.get("otherPathNote"); 649 659 650 660 if (samplingDateTime != null) … … 671 681 if (samplingDateTime != null) Annotationtype.SAMPLING_DATETIME.setAnnotationValue(dc, specimen, samplingDateTime); 672 682 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"))); 673 687 String yellowLabel = (String)jsonSpec.get("YellowLabel"); 674 688 String yellowLabelOriginal = (String)jsonSpec.get("YellowLabelOriginal"); … … 687 701 else 688 702 { 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; 692 711 if (jsonNoSpecimen != null) 693 712 { 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()); 703 714 } 704 715 else 705 716 { 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"))); 739 732 } 740 733 -
extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ReferenceDateServlet.java
r6440 r6510 147 147 caseQuery.order(Orders.asc(Hql.property("parent.id"))); 148 148 149 // Load all child Specimen/NoSpecimen /FutureSpecimenwith a known creation date149 // Load all child Specimen/NoSpecimen with a known creation date 150 150 // IMPORTANT!! Sort by oldest first 151 151 ItemQuery<Sample> specimenQuery = Sample.getQuery(); … … 154 154 Restrictions.or( 155 155 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) 158 157 )); 159 158 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 80 80 import net.sf.basedb.reggie.dao.FlowCell; 81 81 import net.sf.basedb.reggie.dao.FlowThrough; 82 import net.sf.basedb.reggie.dao.FutureSpecimen;83 82 import net.sf.basedb.reggie.dao.Histology; 84 83 import net.sf.basedb.reggie.dao.Library; … … 245 244 ItemSubtype specimenType = Subtype.SPECIMEN.get(dc); 246 245 ItemSubtype noSpecimenType = Subtype.NO_SPECIMEN.get(dc); 247 ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);248 246 249 247 ItemSubtype histologyType = Subtype.HISTOLOGY.get(dc); … … 269 267 JSONArray jsonSpecimen = new JSONArray(); 270 268 JSONArray jsonNoSpecimen = new JSONArray(); 271 JSONArray jsonFutureSpecimen = new JSONArray();272 269 273 270 JSONArray jsonHistology = new JSONArray(); … … 333 330 loadNoSpecimenInfo(dc, ns); 334 331 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());341 332 } 342 333 else if (histologyType.equals(subtype)) … … 428 419 if (jsonSpecimen.size() > 0) json.put("specimen", jsonSpecimen); 429 420 if (jsonNoSpecimen.size() > 0) json.put("noSpecimen", jsonNoSpecimen); 430 if (jsonFutureSpecimen.size() > 0) json.put("futureSpecimen", jsonFutureSpecimen);431 421 432 422 if (jsonHistology.size() > 0) json.put("histology", jsonHistology); … … 493 483 ItemSubtype caseType = Subtype.CASE.get(dc); 494 484 Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc); 495 ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);496 485 ItemSubtype pooledLibraryType = Subtype.POOLED_LIBRARY.get(dc); 497 486 … … 535 524 { 536 525 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;542 526 } 543 527 else if (pooledLibraryType.equals(subtype)) … … 759 743 } 760 744 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 774 745 private void loadNoSpecimenInfo(DbControl dc, NoSpecimen noSpecimen) 775 746 { … … 1383 1354 ItemSubtype caseType = Subtype.CASE.get(dc); 1384 1355 ItemSubtype bloodType = Subtype.BLOOD.get(dc); 1385 ItemSubtype futureSpecimenType = Subtype.FUTURE_SPECIMEN.get(dc);1386 1356 Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc); 1387 1357 … … 1461 1431 itemName + " (" + subtype.getName() + ") is not registered as destroyed"); 1462 1432 } 1463 }1464 1465 if (futureSpecimenType.equals(subtype))1466 {1467 throw new PermissionDeniedException(Permission.DELETE,1468 itemName + ": FutureSpecimen must wait for information from external lab");1469 1433 } 1470 1434
Note: See TracChangeset
for help on using the changeset viewer.