25. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 10/4/2017 8:04:33 AM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

25.1 Files compared

# Location File Last Modified
1 rdk.zip\rdk\product\production\rdk\src\fhir\diagnostic-report diagnostic-report-resource.js Mon Aug 21 12:51:00 2017 UTC
2 rdk.zip\rdk\product\production\rdk\src\fhir\diagnostic-report diagnostic-report-resource.js Tue Oct 3 18:02:10 2017 UTC

25.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 18 1604
Changed 17 34
Inserted 0 0
Removed 0 0

25.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

25.4 Active regular expressions

No regular expressions were active.

25.5 Comparison detail

  1   'use stric t';
  2   var rdk =  require('. ./../core/ rdk');
  3   var nullch ecker = rd k.utils.nu llchecker;
  4   var _ = re quire('lod ash');
  5   var async  = require( 'async');
  6   var labRes ults = req uire('./la b-result-r esource');
  7   var radRep orts = req uire('./ra diology-re port-resou rce');
  8   var fhirRe source = r equire('.. /common/en tities/fhi r-resource ');
  9   var errors  = require ('../commo n/errors') ;
  10   var fhirTo JDSSearch  = require( '../common /utils/fhi r-to-jds-s earch');
  11   var diagno sticReport SortUtils  = require( './diagnos tic-report -sort-util s');
  12   var consta nts = requ ire('../co mmon/utils /constants ');
  13   var jds =  require('. ./common/u tils/jds-q uery-helpe r');
  14   var confUt ils = requ ire('../co nformance/ conformanc e-utils');
  15   var confor mance = re quire('../ conformanc e/conforma nce-resour ce');
  16  
  17   var fhirTo JDSAttrMap  = [{
  18       fhirNa me: 'domai n', // Not e this att ribute is  a app-defi ned search  param, no t a Fhir s pecified a ttribute.
  19       vprNam e: '',
  20       dataTy pe: 'strin g',
  21       defini tion: 'htt p://www.hl 7.org/FHIR /2015May/d atatypes.h tml#string ',
  22       descri ption: 'Th is will sp ecify whic h types of  Diagnosti c Reports  to return.  \'lab\' f or all typ es of labs  (\'LAB\',  \'CH\', \ 'MB\'),  \ 'rad\' for  all radio logy, \'ap \' for all  types of  accession  (\'LAB\',  \'OTH\', \ 'SP\', \'C P\', \'AP\ ').  Usage  example:  domain=lab  . Note: i f both dom ain and se rvice is s pecified,  then servi ce will ta ke precede nt.' ,
  23       search able: true
  24   },{
  25       fhirNa me: 'servi ce', // No te this at tribute is  a app-def ined searc h param, n ot a Fhir  specified  attribute.
  26       vprNam e: '',
  27       dataTy pe: 'strin g',
  28       defini tion: 'htt p://www.hl 7.org/FHIR /2015May/d atatypes.h tml#string ',
  29       descri ption: 'Th is will sp ecify whic h categori es of Diag nostic Rep orts to re turn. \'la b\', \'ch\ ', \'mb\',  \'rad\',  \'oth\', \ 'sp\', \'c p\', \'ap\ '. Usage e xample: se rvice=lab  . Note: if  both doma in and ser vice is sp ecified, t hen servic e will tak e preceden t.' ,
  30       search able: true
  31   },{
  32       fhirNa me: 'subje ct.identif ier', // N ote this a ttribute i s a app-de fined sear ch param,  not a Fhir  specified  attribute .
  33       vprNam e: 'pid',
  34       dataTy pe: 'strin g',
  35       defini tion: 'htt p://www.hl 7.org/FHIR /2015May/d atatypes.h tml#string ',
  36       descri ption: 'Pa tient inde ntifier -  note that  this patie nt identif ier will o verride an y patient  identifier  that is i n the URI  of this en dpoint.',
  37       search able: true
  38   },{
  39       fhirNa me: 'pid',   // Note  this attri bute is a  app-define d search p aram, not  a Fhir spe cified
  40       vprNam e: 'pid',
  41       dataTy pe: 'strin g',
  42       defini tion: 'htt p://www.hl 7.org/FHIR /2015May/d atatypes.h tml#string ',
  43       descri ption: 'Pa tient inde ntifier -  note that  this patie nt identif ier will o verride an y patient  identifier  that has  been speci fied in th e URI of t his endpoi nt, as wel l as any s ubject.ide ntifier in  the query  string.',
  44       search able: true
  45   },{
  46       fhirNa me: 'date' ,
  47       vprNam e: 'observ ed',
  48       dataTy pe: 'dateT ime',
  49       defini tion: 'htt p://www.hl 7.org/FHIR /2015May/d atatypes.h tml#dateTi me',
  50       descri ption: 'Th is is the  date/time  the diagno stic was d one.  The  prefixes > , >=, <=,  < and != m ay be used  on the pa rameter va lue (e.g.  date=>2015 -01-15). T he followi ng date fo rmats are  permitted:  yyyy-mm-d dThh:mm:ss  (exact da te search) , yyyy-mm- dd (within  given day ), yyyy-mm  (within g iven month ), yyyy (w ithin give n year). A  single da te paramet er can be  used for a n exact da te search  (e.g. date =2015-01-2 6T08:30:00 ) or an im plicit ran ge (e.g. d ate=2015-0 1, searche s all date s in Janua ry 2015).  Two date p arameters  can be use d to speci fy an expl icitly bou nded range . When usi ng a pair  of date pa rameters,  the parame ters shoul d bind bot h ends of  the range.  One shoul d have a l ess-than o perator (< , <=) whil e the othe r a greate r-than ope rator (>,  >=).',
  51       search able: true
  52   },{
  53       fhirNa me: '_sort ',
  54       vprNam e: '',
  55       dataTy pe: 'strin g',
  56       defini tion: 'htt p://hl7.or g/FHIR/201 5May/datat ypes.html# string',
  57       descri ption: 'So rt criteri a. Ascendi ng order b y default,  order is  specified  with the f ollowing v ariants:   _sort:asc  (ascending ), _sort:d esc (desce nding). Su pported so rt propert ies: date,  identifie r, issued,  performer , result,  service, s pecimen, s tatus.',
  58       search able: true
  59   }];
  60   confUtils. addCountAt tribute(fh irToJDSAtt rMap); //a dding the  _count att ribute tha t is commo n to (almo st) all en dpoints.
  61  
  62  
  63   // Issue c all to Con formance r egistratio n
  64   conformanc e.register (confUtils .domains.D IAGNOSTIC_ REPORT, cr eateConfor manceData( ));
  65  
  66   function c reateConfo rmanceData () {
  67      var res ourceType  = confUtil s.domains. DIAGNOSTIC _REPORT;
  68      var pro fileRefere nce = 'htt p://www.hl 7.org/FHIR /2015May/d iagnosticr eport.html ';
  69      var int eractions  = [ 'read' , 'search- type' ];
  70  
  71      return  confUtils. createConf ormanceDat a(resource Type, prof ileReferen ce,
  72               interacti ons, fhirT oJDSAttrMa p);
  73   }
  74  
  75   //TODO-FUT URE
  76   // As JSON .parse and  JSON.stri ngify work  in a bloc king manne r perhaps  we should  switch to  a streamin g parser a s this one :
  77   // https:/ /github.co m/dominict arr/JSONSt ream
  78  
  79   //The stop Aggregatin g flag is  used in co njunction  with the _ count para menter.  I t is a sig nal to sto p bundling  additiona l results  while stil l incremen ting the r esult coun t total.
  80   var stopAg gregating;
  81   var fhirTo JDSSortMap  = diagnos ticReportS ortUtils.g etFhirToJD SMap();
  82  
  83   var domain s = {
  84       'lab':  'laborato ry',
  85       'rad':  'imaging' ,
  86       'ap':  'accession '
  87   };
  88  
  89   var labCat egoryPrefi x = 'urn:v a:lab-cate gory:';
  90  
  91   var labora toryServic eCategorie s = ['LAB' , 'CH', 'M B'];
  92   var imagin gServiceCa tegories =  ['RAD'];
  93   var access ionService Categories  = ['LAB',  'OTH', 'S P', 'CP',  'AP'];
  94  
  95   function g etResource Config() {
  96       return  [{
  97           na me: 'fhir- diagnostic -report',
  98           pa th: '',
  99           ge t: getDiag nosticRepo rts,
  100           su bsystems:  ['patientr ecord', 'j ds', 'solr ', 'jdsSyn c', 'autho rization'] ,
  101           re quiredPerm issions: [ 'read-fhir '],
  102           is PatientCen tric: true ,
  103           in terceptors : {
  104                fhirPid:  true,
  105                validate Pid: false
  106           },
  107           pe rmitRespon seFormat:  true
  108       },{
  109           na me: 'fhir- diagnostic -report-se arch',
  110           pa th: '_sear ch',
  111           po st: getDia gnosticRep orts,
  112           su bsystems:  ['patientr ecord', 'j ds', 'solr ', 'jdsSyn c', 'autho rization'] ,
  113           re quiredPerm issions: [ 'read-fhir '],
  114           is PatientCen tric: true ,
  115           in terceptors : {
  116                fhirPid:  true,
  117                validate Pid: false
  118           },
  119           pe rmitRespon seFormat:  true
  120       }];
  121   }
  122  
  123   function v alidatePar ams(params , onSucces s, onError ) {
  124       stopAg gregating  = false;
  125       // che ck common  parameters
  126       fhirTo JDSSearch. validateCo mmonParams (params, f unction()  {
  127           //  validate  date
  128           fh irToJDSSea rch.valida teDatePara ms(params,  ['date'],  function( ) {
  129                if (fhir ToJDSSearc h.isSortCr iteriaVali d(params,  fhirToJDSS ortMap)) {
  130                    onSu ccess();
  131                } else {
  132                    onEr ror(['Unsu pported _s ort criter ia. Suppor ted attrib utes are:  date, iden tifier, is sued, perf ormer, res ult, speci men and st atus']);
  133                }
  134           },  onError);
  135       }, onE rror);
  136   }
  137  
  138   /**
  139    * @api {g et} /fhir/ patient/{i d}/diagnos ticreport  Get Diagno stic Repor ts
  140    * @apiNam e getDiagn osticRepor t
  141    * @apiGro up Diagnos tic Report
  142    * @apiPar am {String } id The p atient id
  143    * @apiPar am {String } [domain]  The domai n to filte r on.  Cho ices inclu de: lab',  rad, ap
  144    * @apiPar am {String } [service ] The diag nostic dis cipline/de partment w hich creat ed the rep ort
  145    * @apiPar am {Number } [_count]  The numbe r of resul ts to show .
  146    * @apiPar am {String } [date] O btained da te/time. T he prefixe s >, >=, < =, < and ! = may be u sed on the  parameter  value (e. g. date=>2 015-01-15) . The foll owing date  formats a re permitt ed: yyyy-m m-ddThh:mm :ss (exact  date sear ch), yyyy- mm-dd (wit hin given  day), yyyy -mm (withi n given mo nth), yyyy  (within g iven year) . A single  date para meter can  be used fo r an exact  date sear ch (e.g. d ate=2015-0 1-26T08:30 :00) or an  implicit  range (e.g . date=201 5-01, sear ches all d ates in Ja nuary 2015 ). Two dat e paramete rs can be  used to sp ecify an e xplicitly  bounded ra nge. When  using a pa ir of date  parameter s, the par ameters sh ould bind  both ends  of the ran ge. One sh ould have  a less-tha n operator  (<, <=) w hile the o ther a gre ater-than  operator ( >, >=). Co nsult the  <a href="h ttp://www. hl7.org/FH IR/2015May /search.ht ml#date">F HIR DSTU2  API</a> do cumentatio n for more  informati on.
  147    * @apiPar am {String } [_sort]  Sort crite ria. Ascen ding order  by defaul t, order i s specifie d with the  following  variants:   _sort:as c (ascendi ng), _sort :desc (des cending).  Supported  sort prope rties: dat e, identif ier, issue d, perform er, result , service,  specimen,  status.
  148    *
  149    * @apiDes cription C onverts vp r \'labrat ory,\' \'i maging\' a nd \'acces sion\' res ources int o a FHIR \ 'diagnosti creport\'  resource.
  150    *
  151    * @apiExa mple {js}  Request Ex amples:
  152    *      //  Diagnosti cReport li miting res ults count
  153    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?_count=1
  154    *
  155    *      //  Diagnosti cReport ex act date s earch
  156    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=201 5-01-26T13 :45:00
  157    *
  158    *      //  Diagnosti cReport on  a day
  159    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=201 5-01-26
  160    *
  161    *      //  Diagnosti cReport on  a month
  162    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=201 5-01
  163    *
  164    *      //  Diagnosti cReport on  a year
  165    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=201 5
  166    *
  167    *      //  Diagnosti cReport ou tside a da te range ( e.g. Diagn osticRepor ts not occ uring on J anuary 201 5)
  168    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=!=2 015-01
  169    *
  170    *      //  Diagnosti cReport Ex plicit dat e range
  171    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?date=>=2 014-06&dat e=<=2014-0 9-20
  172    *
  173    *      //  Diagnosti cReport so rted by da te (sorts  by Diagnos ticReport. appliesDat eTime)
  174    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?_sort=da te
  175    *
  176    *      //  Diagnosti cReport so rted by da te in desc ending ord er
  177    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?_sort:de sc=date
  178    *
  179    *      //  Diagnosti cReport so rted by pe rformer (s orts by Di agnosticRe port.perfo rmer.displ ay)
  180    *        http:// IP             /resource/ fhir/patie nt/ R E D A CTED ;253/diagn osticrepor t?_sort=pe rformer
  181    *
  182    * @apiSuc cess {json } data Jso n object c onforming  to the <a  href="http ://www.hl7 .org/FHIR/ 2015May/di agnosticre port.html" >Diagnosti cReport FH IR DTSU2 s pecificati on</a>.
  183    * @apiSuc cessExampl e Success- Response:
  184    * HTTP/1. 1 200 OK
  185    *{
  186    *  "resou rceType":  "Bundle",
  187    *  "type" : "collect ion",
  188    *  "id":  "ccbd2fd7- 486a-41a8- f08e-ef53e 5a00689",
  189    *  "link" : [
  190    *    {
  191    *      "r elation":  "self",
  192    *        "url": "ht tp://local host:8888/ resource/f hir/patien t/ R E D A CTED ;253/diagn osticrepor t?domain=l ab&_count= 1&date=201 0&_sort=da te"
  193    *    }
  194    *  ],
  195    *  "total ": 18,
  196    *  "entry ": [
  197    *    {
  198    *      "r esource":  {
  199    *         "resourceT ype": "Dia gnosticRep ort",
  200    *         "name": {
  201    *           "text":  "POTASSIUM ",
  202    *           "coding" : [
  203    *             {
  204    *               "sys tem": "urn :oid:2.16. 840.1.1138 83.6.233",
  205    *               "cod e": "urn:v a:ien:60:1 77:72",
  206    *               "dis play": "PO TASSIUM"
  207    *             }
  208    *           ]
  209    *         },
  210    *         "status":  "final",
  211    *         "issued":  "2010-03-2 3T11:04:00 +08:00",
  212    *         "subject":  {
  213    *            "reference ": "Patien t/ R E D A CTED ;253"
  214    *         },
  215    *         "performer ": {
  216    *           "referen ce": "#737 894fd-760e -4ac4-b304 -1fbcfefd7 674",
  217    *           "display ": "ALBANY  VA MEDICA L CENTER"
  218    *         },
  219    *         "contained ": [
  220    *           {
  221    *             "resou rceType":  "Organizat ion",
  222    *             "id":  "737894fd- 760e-4ac4- b304-1fbcf efd7674",
  223    *             "ident ifier": [
  224    *               {
  225    *                 "t ype": {
  226    *                    "text": "f acility-co de"
  227    *                 },
  228    *                 "v alue": "50 0"
  229    *               }
  230    *             ],
  231    *             "name" : "ALBANY  VA MEDICAL  CENTER",
  232    *             "addre ss": [
  233    *               {
  234    *                 "t ext": "VA  MEDICAL CE NTER 1 3RD  sT. ALBAN Y, NY 1218 0-0097",
  235    *                 "s tate": "NY ",
  236    *                 "c ity": "ALB ANY",
  237    *                 "l ine": [
  238    *                    "ALBANY VA  MEDICAL C ENTER",
  239    *                    "VA MEDICA L CENTER 1  3RD sT."
  240    *                 ],
  241    *                 "p ostalCode" : "12180-0 097"
  242    *               }
  243    *             ],
  244    *             "text" : {
  245    *               "sta tus": "gen erated",
  246    *               "div ": "<div>A LBANY VA M EDICAL CEN TER<br/>VA  MEDICAL C ENTER 1 3R D sT. ALBA NY, NY 121 80-0097</d iv>"
  247    *             }
  248    *           },
  249    *           {
  250    *             "resou rceType":  "Specimen" ,
  251    *             "id":  "6ec1bec2- c167-41b3- e905-34267 c92dd3b",
  252    *             "type" : {
  253    *               "tex t": "SERUM "
  254    *             },
  255    *             "subje ct": {
  256    *                 "reference ": "Patien t/ R E D A CTED ;253"
  257    *             },
  258    *             "colle ction": {
  259    *               "col lectedDate Time": "20 10-03-05T0 9:00:00+08 :00"
  260    *             }
  261    *           },
  262    *           {
  263    *             "resou rceType":  "Observati on",
  264    *             "id":  "fd352966- 8eb4-4be3- dc4b-3849b 06c4152",
  265    *             "code" : {
  266    *               "tex t": "POTAS SIUM",
  267    *               "cod ing": [
  268    *                 {
  269    *                    "system":  "urn:oid:2 .16.840.1. 113883.6.2 33",
  270    *                    "code": "u rn:va:ien: 60:177:72" ,
  271    *                    "display":  "POTASSIU M"
  272    *                 }
  273    *               ]
  274    *             },
  275    *             "statu s": "final ",
  276    *             "value Quantity":  {
  277    *               "val ue": 4.1,
  278    *               "uni ts": "meq/ L"
  279    *             },
  280    *             "relia bility": " ok",
  281    *             "speci men": {
  282    *               "ref erence": " #6ec1bec2- c167-41b3- e905-34267 c92dd3b",
  283    *               "dis play": "SE RUM"
  284    *             },
  285    *             "refer enceRange" : [
  286    *               {
  287    *                 "h igh": {
  288    *                    "value": 5 .3,
  289    *                    "units": " meq/L"
  290    *                 },
  291    *                 "l ow": {
  292    *                    "value": 3 .8,
  293    *                    "units": " meq/L"
  294    *                 }
  295    *               }
  296    *             ]
  297    *           }
  298    *         ],
  299    *         "identifie r": [
  300    *           {
  301    *             "syste m": "urn:o id:2.16.84 0.1.113883 .6.233",
  302    *               "value": " urn:va:lab : R E D A CTED :253:CH;68 99693.9099 99;6"
  303    *           }
  304    *         ],
  305    *         "serviceCa tegory": {
  306    *           "text":  "Chemistry ",
  307    *           "coding" : [
  308    *             {
  309    *               "sys tem": "htt p://hl7.or g/fhir/v2/ 0074",
  310    *               "cod e": "CH",
  311    *               "dis play": "Ch emistry"
  312    *             }
  313    *           ]
  314    *         },
  315    *         "diagnosti cDateTime" : "2010-03 -05T09:00: 00+08:00",
  316    *         "specimen" : [
  317    *           {
  318    *             "refer ence": "#6 ec1bec2-c1 67-41b3-e9 05-34267c9 2dd3b",
  319    *             "displ ay": "SERU M"
  320    *           }
  321    *         ],
  322    *         "extension ": [
  323    *           {
  324    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#abnormal ",
  325    *             "value Boolean":  false
  326    *           },
  327    *           {
  328    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#category Code",
  329    *             "value String": " urn:va:lab -category: CH"
  330    *           },
  331    *           {
  332    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#category Name",
  333    *             "value String": " Laboratory "
  334    *           },
  335    *           {
  336    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#displayN ame",
  337    *             "value String": " K"
  338    *           },
  339    *           {
  340    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#displayO rder",
  341    *             "value Decimal":  1.2
  342    *           },
  343    *           {
  344    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#facility Code",
  345    *             "value String": " 500"
  346    *           },
  347    *           {
  348    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#groupNam e",
  349    *             "value String": " CH 0323 42 5"
  350    *           },
  351    *           {
  352    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#groupUid ",
  353    *               "valueStri ng": "urn: va:accessi on: R E D A CTED :253:CH;68 99693.9099 99"
  354    *           },
  355    *           {
  356    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#high",
  357    *             "value String": " 5.3"
  358    *           },
  359    *           {
  360    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#kind",
  361    *             "value String": " Laboratory "
  362    *           },
  363    *           {
  364    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#localId" ,
  365    *             "value String": " CH;6899693 .909999;6"
  366    *           },
  367    *           {
  368    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#micro",
  369    *             "value Boolean":  false
  370    *           },
  371    *           {
  372    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#pid",
  373    *               "valueStri ng": " R E D A CTED ;253"
  374    *           },
  375    *           {
  376    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#qualifie dName",
  377    *             "value String": " POTASSIUM  (SERUM)"
  378    *           },
  379    *           {
  380    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#result",
  381    *             "value String": " 4.1"
  382    *           },
  383    *           {
  384    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#specimen ",
  385    *             "value String": " SERUM"
  386    *           },
  387    *           {
  388    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#stampTim e",
  389    *             "value String": " 2010032311 0400"
  390    *           },
  391    *           {
  392    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#statusCo de",
  393    *             "value String": " urn:va:lab -status:co mpleted"
  394    *           },
  395    *           {
  396    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#summary" ,
  397    *             "value String": " POTASSIUM  (SERUM) 4. 1 meq/L"
  398    *           },
  399    *           {
  400    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#typeId",
  401    *             "value Integer":  177
  402    *           },
  403    *           {
  404    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#units",
  405    *             "value String": " meq/L"
  406    *           },
  407    *           {
  408    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#lastUpda teTime",
  409    *             "value String": " 2010032311 0400"
  410    *           },
  411    *           {
  412    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#low",
  413    *             "value String": " 3.8"
  414    *           },
  415    *           {
  416    *             "url":  "http://v istacore.u s/fhir/ext ensions/la b#lnccodes [0]",
  417    *             "value String": " urn:va:ien :60:177:72 "
  418    *           }
  419    *         ],
  420    *         "result":  [
  421    *           {
  422    *             "refer ence": "#f d352966-8e b4-4be3-dc 4b-3849b06 c4152",
  423    *             "displ ay": "POTA SSIUM"
  424    *           }
  425    *         ],
  426    *         "text": {
  427    *           "status" : "generat ed",
  428    *            "div": "<d iv>Collect ed: 2010-0 3-05T09:00 :00<br/>Re port Relea sed: 2010- 03-23T11:0 4:00<br/>A ccession:  urn:va:acc ession: R E D A CTED :253:CH;68 99693.9099 99<br/>Tes t: POTASSI UM<br/>Res ult: 4.1 m eq/L<br/>L ow: 3.8 me q/L<br/>Hi gh: 5.3 me q/L<br/>Sp ecimen: SE RUM<br/>Pe rforming L ab: ALBANY  VA MEDICA L CENTER<b r/>\t\tund efined<br/ >\t\tundef ined<br/>< /div>"
  429    *         }
  430    *      }
  431    *    }
  432    *  ]
  433    *}
  434    *
  435    * @apiErr or (Error  400) Inval id paramet er values.
  436    * @apiErr orExample  Error-Resp onse:
  437    * HTTP/1. 1 400 Bad  Request
  438    * {
  439    *      In valid para meter valu es.
  440    * }
  441    */
  442   function g etDiagnost icReports( req, res)  {
  443       var pi d = req.qu ery.pid;
  444       if (nu llchecker. isNullish( pid)) {
  445           re turn res.s tatus(rdk. httpstatus .bad_forma t).send('M issing req uired para meter: pid ');
  446       }
  447       //lab  & radiolog y are expe cting this  value in  _pid, assi gn it here  as a safe ty check
  448       req._p id = pid;
  449  
  450       var do main = req .param('do main');
  451       var se rvice = re q.param('s ervice');
  452       var se rviceCateg ories = [] ;
  453       var pa rams = req .query;
  454       if (nu llchecker. isNullish( service))  {
  455           if  (nullchec ker.isNotN ullish(dom ain)) {
  456                serviceC ategories. push(domai n.toUpperC ase());
  457           }  else {
  458                serviceC ategories  = serviceC ategories. concat(lab oratorySer viceCatego ries);
  459                serviceC ategories  = serviceC ategories. concat(ima gingServic eCategorie s);
  460                serviceC ategories  = serviceC ategories. concat(acc essionServ iceCategor ies);
  461           }
  462       } else  {
  463           se rviceCateg ories = se rviceCateg ories.conc at(service .toUpperCa se().split (','));
  464       }
  465  
  466       valida teParams(p arams, fun ction() {
  467           ge tDiagnosti cReportsIm pl(pid, re q, res, pa rams, serv iceCategor ies);
  468       }, fun ction(erro rs) {
  469           re turn res.s tatus(rdk. httpstatus .bad_reque st).send(' Invalid pa rameters:'  + fhirToJ DSSearch.v alidationE rrorsToStr ing(errors ));
  470       });
  471   }
  472  
  473   function g etDiagnost icReportsI mpl(pid, r eq, res, p arams, ser viceCatego ries) {
  474       var co unt = req. param('_co unt');
  475  
  476       var as yncTasks =  [];
  477       asyncT asks.push( function(c allback) {
  478           ca llback(nul l, {
  479                results:  [],
  480                totalIte ms: 0
  481           }) ;
  482       });
  483  
  484       // lab oratory
  485       if (nu llchecker. isNullish( serviceCat egories) | | (nullche cker.isNot Nullish(se rviceCateg ories) &&  _.intersec tion(labor atoryServi ceCategori es, servic eCategorie s).length  > 0)) {
  486           va r labCateg oryCodes =  [];
  487           va r intersec tionLabora tory = [];
  488           if  (nullchec ker.isNotN ullish(ser viceCatego ries)) {
  489                intersec tionLabora tory = _.i ntersectio n(laborato ryServiceC ategories,  serviceCa tegories);
  490           }
  491           if  (!_.conta ins(inters ectionLabo ratory, 'L AB')) {
  492                for (var  labCC in  labResults .categoryM ap) {
  493                    if ( _.contains (intersect ionLaborat ory, labRe sults.cate goryMap[la bCC].code) ) {
  494                         labCategor yCodes.pus h(labCateg oryPrefix  + labCC);
  495                    }
  496                }
  497           }
  498           as yncTasks.p ush(functi on(accumul ator, call back) {
  499                var limi tRemainder  = count;
  500                if (null checker.is NotNullish (count) &&  accumulat or && accu mulator.re sults && a ccumulator .results.l ength) {
  501                    limi tRemainder  -= accumu lator.resu lts.length ;
  502                }
  503                if (limi tRemainder  === 0) {
  504                    stop Aggregatin g = true;
  505                }
  506                getVprDa ta(pid, re q, domains .lab, labC ategoryCod es, limitR emainder,  params, fu nction(err , inputJSO N) {
  507                    var  error = nu ll;
  508                    var  result = n ull;
  509  
  510                    if ( err instan ceof error s.ParamErr or) {
  511                         error = {
  512                             code:  rdk.httpst atus.bad_r equest,
  513                             messag e: err.mes sage
  514                         };
  515                    } el se if (err  instanceo f errors.N otFoundErr or) {
  516                         error = {
  517                             code:  rdk.httpst atus.not_f ound,
  518                             messag e: err.err or
  519                         };
  520                    } el se if (err  instanceo f errors.F etchError)  {
  521                         req.logger .error(err .message);
  522                         error = {
  523                             code:  rdk.httpst atus.inter nal_server _error,
  524                             messag e: 'There  was an err or process ing your r equest. Th e error ha s been log ged.'
  525                         };
  526                    } el se if (err ) {
  527                         error = {
  528                             code:  rdk.httpst atus.inter nal_server _error,
  529                             messag e: err.mes sage
  530                         };
  531                    } el se {
  532                         result = l abResults. convertToF hir(inputJ SON, req);
  533                         if (!stopA ggregating ) {
  534                             accumu lator.resu lts = accu mulator.re sults.conc at(result) ;
  535                         }
  536                         accumulato r.totalIte ms += inpu tJSON.data .totalItem s;
  537                    }
  538  
  539                    call back(error , accumula tor); //ca ll final c allback
  540  
  541                });
  542           }) ;
  543       }
  544       // acc ession
  545       if (nu llchecker. isNullish( serviceCat egories) | | (nullche cker.isNot Nullish(se rviceCateg ories) &&  _.intersec tion(acces sionServic eCategorie s, service Categories ).length >  0)) {
  546           va r apCatego ryCodes =  [];
  547           va r intersec tionAccess ion = [];
  548           if  (nullchec ker.isNotN ullish(ser viceCatego ries)) {
  549                intersec tionAccess ion = _.in tersection (accession ServiceCat egories, s erviceCate gories);
  550           }
  551           if  (_.inters ection(int ersectionA ccession,  ['LAB', 'A P']).lengt h === 0) {
  552                for (var  apCC in l abResults. categoryMa p) {
  553                    if ( _.contains (intersect ionAccessi on, labRes ults.categ oryMap[apC C].code))  {
  554                         apCategory Codes.push (labCatego ryPrefix +  apCC);
  555                    }
  556                }
  557           }
  558           as yncTasks.p ush(functi on(accumul ator, call back) {
  559                var limi tRemainder  = count;
  560                if (null checker.is NotNullish (count) &&  accumulat or && accu mulator.re sults && a ccumulator .results.l ength) {
  561                    limi tRemainder  -= accumu lator.resu lts.length ;
  562                }
  563                if (limi tRemainder  === 0) {
  564                    stop Aggregatin g = true;
  565                }
  566                getVprDa ta(pid, re q, domains .ap, apCat egoryCodes , limitRem ainder, pa rams, func tion(err,  inputJSON)  {
  567                    var  error = nu ll;
  568                    var  result = n ull;
  569  
  570                    if ( err instan ceof error s.ParamErr or) {
  571                         error = {
  572                             code:  rdk.httpst atus.bad_r equest,
  573                             messag e: err.mes sage
  574                         };
  575                    } el se if (err  instanceo f errors.N otFoundErr or) {
  576                         error = {
  577                             code:  rdk.httpst atus.not_f ound,
  578                             messag e: err.err or
  579                         };
  580                    } el se if (err  instanceo f errors.F etchError)  {
  581                         req.logger .error(err .message);
  582                         error = {
  583                             code:  rdk.httpst atus.inter nal_server _error,
  584                             messag e: 'There  was an err or process ing your r equest. Th e error ha s been log ged.'
  585                         };
  586                    } el se if (err ) {
  587                         error = {
  588                             code:  rdk.httpst atus.inter nal_server _error,
  589                             messag e: err.mes sage
  590                         };
  591                    } el se {
  592                         result = l abResults. convertToF hir(inputJ SON, req);
  593                         if (!stopA ggregating ) {
  594                             accumu lator.resu lts = accu mulator.re sults.conc at(result) ;
  595                         }
  596                         accumulato r.totalIte ms += inpu tJSON.data .totalItem s;
  597                    }
  598  
  599                    call back(error , accumula tor); //ca ll final c allback
  600  
  601                });
  602           }) ;
  603       }
  604       // ima ging
  605       if (nu llchecker. isNullish( serviceCat egories) | | (nullche cker.isNot Nullish(se rviceCateg ories) &&  _.intersec tion(imagi ngServiceC ategories,  serviceCa tegories). length > 0 )) {
  606           va r radCateg oryCodes =  [];
  607           as yncTasks.p ush(functi on(accumul ator, call back) {
  608                var limi tRemainder  = count;
  609                if (null checker.is NotNullish (count) &&  accumulat or && accu mulator.re sults && a ccumulator .results.l ength) {
  610                    limi tRemainder  -= accumu lator.resu lts.length ;
  611                }
  612                if (limi tRemainder  === 0) {
  613                    stop Aggregatin g = true;
  614                }
  615                getVprDa ta(pid, re q, domains .rad, radC ategoryCod es, limitR emainder,  params, fu nction(err , inputJSO N) {
  616                    var  error = nu ll;
  617                    var  result = n ull;
  618  
  619                    if ( err instan ceof error s.ParamErr or) {
  620                         error = {
  621                             code:  rdk.httpst atus.bad_r equest,
  622                             messag e: err.mes sage
  623                         };
  624                    } el se if (err  instanceo f errors.N otFoundErr or) {
  625                         error = {
  626                             code:  rdk.httpst atus.not_f ound,
  627                             messag e: err.err or
  628                         };
  629                    } el se if (err  instanceo f errors.F etchError)  {
  630                         req.logger .error(err .message);
  631                         error = {
  632                             code:  rdk.httpst atus.inter nal_server _error,
  633                             messag e: 'There  was an err or process ing your r equest. Th e error ha s been log ged.'
  634                         };
  635                    } el se if (err ) {
  636                         error = {
  637                             code:  rdk.httpst atus.inter nal_server _error,
  638                             messag e: err.mes sage
  639                         };
  640                    } el se {
  641                         result = r adReports. convertToF hir(inputJ SON, req);
  642                         if (!stopA ggregating ) {
  643                             accumu lator.resu lts = accu mulator.re sults.conc at(result) ;
  644                         }
  645                         accumulato r.totalIte ms += inpu tJSON.data .totalItem s;
  646                    }
  647  
  648                    call back(error , accumula tor); //ca ll final c allback
  649  
  650                });
  651           }) ;
  652       }
  653  
  654       async. waterfall( asyncTasks , function (err, accu mulator) {  //final c allback
  655           if  (nullchec ker.isNotN ullish(err )) {
  656                res.stat us(err.cod e || 500). send(err.m essage);
  657           }  else {
  658                var bund le = build Bundle(acc umulator.r esults, re q, accumul ator.total Items);
  659                res.stat us(200).se nd(bundle) ;
  660           }
  661       });
  662   }
  663  
  664   function b uildBundle (results,  req, total ) {
  665       var en try = [];
  666       var li nk = [];
  667  
  668       if (re q) {
  669           li nk.push(ne w fhirReso urce.Link( req.protoc ol + '://'  + req.hea ders.host  + req.orig inalUrl, ' self'));
  670       }
  671       for (v ar i = 0;  i < result s.length;  i++) {
  672           if  (nullchec ker.isNotN ullish(res ults[i]))  {
  673                var e =  new fhirRe source.Ent ry(results [i]);
  674                // This  IS on the  DSTU2 spec  but the H API valida tion tool  complains  about it.  We're not  adding any  meaninful
  675                // infor mation on  the link s o it is sa fe to be c ommented o ut for the  moment.
  676                //e.link  = [new fh irResource .Link(req. protocol +  '://' + r eq.headers .host + '/ fhir/diagn osticrepor t/' + (e.r esource._i d || e.res ource.id | | '@null') , 'self')] ;
  677                entry.pu sh(e);
  678           }
  679       }
  680  
  681       //Diag nosticRepo rt is an a ggregate o f multiple  reports,  its result s must be  sorted aft er all VPR  calls
  682       entry  = diagnost icReportSo rtUtils.so rtEntries( req, entry );
  683       return  (new fhir Resource.B undle(link , entry, t otal));
  684   }
  685  
  686   /**
  687    * Builds  the corres ponding JD S query fo r the FHIR  Diagnosti cReport.na me search  token quer y.
  688    *
  689    * The nam e query is  of type t oken. It s upports a  comma deli mited list  of code t oken queri es. Each
  690    * token c an include  a code or  a system  AND code q uery separ ated by a  '|'.
  691    *
  692    * Ex.  na me=myCode, anotherCod e,mySystem |myOtherCo de,...
  693    */
  694   function b uildNameCo deQuery(na me) {
  695       var qu eries = [] ;
  696       // FHI R supports  escaped c ommas (\,) . We repla ce non-esc aped comma s with a
  697       // unu sed unicod e characte r to perfo rm the spl it .
  698       var to kens = nam e.replace( /([^\\]),/ g, '$1\u00 0B').split ('\u000B') ;
  699  
  700       _.forE ach(tokens , function (token) {
  701           //  unescape  any commas
  702           to ken = toke n.replace( /\\,/g, ', ');
  703           va r code;
  704           va r system;
  705           va r codeSyst emSplit =  token.spli t('|');
  706  
  707           if  (codeSyst emSplit.le ngth > 1)  {
  708                system =  codeSyste mSplit[0];
  709                code = c odeSystemS plit[1];
  710  
  711           }  else {
  712                code = c odeSystemS plit[0];
  713           }
  714  
  715           if  (nullchec ker.isNotN ullish(sys tem)) {
  716                // ** Sy stem & Cod e **
  717  
  718                // LAB_R ESULTS_UID _IDENTIFIE R_SYSTEM a nd VHA_SYS TEM hold c urrently t he same va lue
  719                // but t hat doesn' t have to  be always  the case.  We don't u se if-else if for tha t reason.
  720                if (syst em === con stants.lab ResultsFhi r.LAB_RESU LTS_UID_ID ENTIFIER_S YSTEM || s ystem ===  constants. labResults Fhir.VHA_S YSTEM) {
  721                    // L AB_RESULTS _UID_IDENT IFIER_SYST EM does no t exist in  VPR, FHIR  mapping a ssociates  the code w ith VPR re cord's vui d
  722                    quer ies.push(j ds.eq('vui d', '\"' +  code + '\ "'));
  723                    // V HA_SYSTEM  does not e xist in VP R, FHIR ma pping asso ciates the  code with  VPR recor d's typeCo de
  724                    quer ies.push(j ds.eq('typ eCode', '\ "' + code  + '\"'));
  725                    // F HIR mappin g associat es the dis play value  for these  systems t o VPR reco rd's typeN ame
  726                    quer ies.push(j ds.eq('typ eName', '\ "' + code  + '\"'));
  727                } else {
  728                    // a ll other s ystem|code  query com binations  can only b e mapped t o the VPR  codes arra y
  729                    quer ies.push(j ds.and(jds .eq('\"cod es[].syste m\"', syst em), jds.o r(jds.eq(' \"codes[]. code\"', ' \"' + code  + '\"'),  jds.eq('\" codes[].di splay\"',  '\"' + cod e + '\"')) ));
  730                }
  731           }  else if (c ode === co nstants.la bResultsFh ir.PATHOLO GY_REPORT_ NAME) {
  732                // ** LR  ANATOMIC  PATHOLOGY  REPORT **
  733                // FHIR  mapping se ts this na me for ite ms with ca tegoryCode  that ends  with AP,  so if sear ching for  this strin g
  734                // we sh ould searc h for item s with cat egoryCode  that ends  in AP.
  735                queries. push(jds.l ike('categ oryCode',  '%AP'));
  736           }  else {
  737                // ** Co de **
  738                var sear chProps =  ['typeName ', 'typeCo de', '\"re sults[].lo calTitle\" ', 'vuid',  '\"codes[ ].code\"',  '\"codes[ ].display\ "'];
  739                var code Queries =  _.map(sear chProps, f unction(pr op) {
  740                    retu rn jds.eq( prop, '\"'  + code +  '\"');
  741                });
  742                queries. push(jds.o r(codeQuer ies));
  743           }
  744       });
  745       // com bine all t oken queri es into OR  expressio ns
  746       return  jds.or(qu eries);
  747   }
  748  
  749   function b uildSearch Query(para ms, catego ryCodes) {
  750       var qu ery = [];
  751       var da teQuery;
  752       var na meQuery;
  753  
  754       // cat egories
  755       if (!_ .isEmpty(c ategoryCod es)) {
  756           qu ery.push(' in(categor yCode,[' +  categoryC odes.join( ',') + ']) ');
  757       }
  758       // nam e (system  & code)
  759       if (nu llchecker. isNotNulli sh(params. name)) {
  760           na meQuery =  buildNameC odeQuery(p arams.name );
  761           if  (nameQuer y) {
  762                query.pu sh(nameQue ry);
  763           }
  764       }
  765       // dat e
  766       if (nu llchecker. isNotNulli sh(params. date)) {
  767           da teQuery =  fhirToJDSS earch.buil dDateQuery (params.da te, 'obser ved');
  768           if  (dateQuer y) {
  769                query.pu sh(dateQue ry);
  770           }
  771       }
  772       return  fhirToJDS Search.bui ldSearchQu eryString( query);
  773   }
  774  
  775   function b uildJDSPat h(pid, par ams, domai n, categor yCodes) {
  776       var ba sePath = ' /vpr/' + p id + '/ind ex/' + dom ain;
  777       var se archQuery  = buildSea rchQuery(p arams, cat egoryCodes );
  778       return  fhirToJDS Search.bui ldJDSPath( basePath,  searchQuer y, params,  fhirToJDS SortMap);
  779   }
  780  
  781   function g etVprData( pid, req,  domain, ca tegoryCode s, count,  params, ca llback) {
  782  
  783       var co nfig = req .app.confi g;
  784  
  785       if (nu llchecker. isNullish( pid)) {
  786           re turn callb ack(new er rors.Param Error('sub ject.ident ifier'));
  787       }
  788  
  789       var jd sPath = bu ildJDSPath (pid, para ms, domain , category Codes);
  790       var op tions = _. extend({},  config.jd sServer, {
  791           ur l: jdsPath ,
  792           lo gger: req. logger,
  793           js on: true
  794       });
  795  
  796       rdk.ut ils.http.g et(options , function (error, re sponse, ob j) {
  797           re q.logger.d ebug('call back from  fetch()');
  798           if  (error) {
  799                return c allback(ne w errors.F etchError( 'Error fet ching pid= ' + pid +  ' - ' + (e rror.messa ge || erro r), error) );
  800           }
  801           if  ('data' i n obj) {
  802                return c allback(nu ll, obj);
  803           }
  804           if  ('error'  in obj) {
  805                if (erro rs.isNotFo und(obj))  {
  806                    retu rn callbac k(new erro rs.NotFoun dError('Ob ject not f ound', obj ));
  807                }
  808                return c allback(ne w errors.F etchError( 'There was  an error  processing  your requ est. The e rror has b een logged .', obj.er ror));
  809           }
  810           re turn callb ack(new er rors.Fetch Error('The re was an  error proc essing you r request.  The error  has been  logged.')) ;
  811       });
  812   }
  813  
  814   module.exp orts.getRe sourceConf ig = getRe sourceConf ig;
  815   module.exp orts.build Bundle = b uildBundle ;
  816   module.exp orts.valid ateParams  = validate Params;
  817   module.exp orts.build JDSPath =  buildJDSPa th;
  818   module.exp orts.creat eConforman ceData = c reateConfo rmanceData ;
  819