| 1 | XWB2HL7 ;ISF/RWF - Remote RPC via HL7 ;04/30/2003  15:20
 | 
|---|
| 2 |  ;;1.1;RPC BROKER;**12,18,20,22,27,32,39**;Mar 28, 1997
 | 
|---|
| 3 |  ;
 | 
|---|
| 4 |  Q
 | 
|---|
| 5 |  ;
 | 
|---|
| 6 |  ; EN1^XLWB2HL7 is the entry point used by the Broker.
 | 
|---|
| 7 |  ;
 | 
|---|
| 8 |  ; Patch XWB*1.1*27 modified the EN1^XWB2HL7 call point.  However,
 | 
|---|
| 9 |  ; the code associated with the original pre-modification version
 | 
|---|
| 10 |  ; of the EN1 call point still exists in the XWB2HL7C routine.
 | 
|---|
| 11 |  ; Please note that when the original EN1 code was moved to XWB2HL7C
 | 
|---|
| 12 |  ; it was renamed OLDEN1.
 | 
|---|
| 13 |  ;
 | 
|---|
| 14 | EN1(RET,LOC,RPC,RPCVER,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10) ; Call a remote RPC
 | 
|---|
| 15 |  ; with 1-10 parameters. (This tag is called from EN1^XWB2HL7.  
 | 
|---|
| 16 |  ; This reworked EN1 call point replaces the original EN1 call point,
 | 
|---|
| 17 |  ; which was renamed OLDEN1.)
 | 
|---|
| 18 |  ;
 | 
|---|
| 19 |  N I,INX,N,PMAX,RPCIEN,X,XWBDVER,XWBESSO,XWBHDL,XWBHL7,XWBMSG
 | 
|---|
| 20 |  N XWBPAR,XWBPCNT,XWBSEC,ZTDESC,ZTDTH,ZTIO,ZTRTN,ZTSAVE,ZTSK
 | 
|---|
| 21 |  ;
 | 
|---|
| 22 |  D SETUP(1) I $G(RET(1))'="" QUIT  ;->
 | 
|---|
| 23 |  ;
 | 
|---|
| 24 |  ; Queue up request... (OLDEN1 used DIRECT call)
 | 
|---|
| 25 |  S ZTSAVE("*")="",ZTRTN="DEQ^XWB2HL7C",ZTDTH=$H,ZTIO=""
 | 
|---|
| 26 |  S ZTDESC="RPC Broker queued call from EN1~XWB2HL7"
 | 
|---|
| 27 |  D ^%ZTLOAD
 | 
|---|
| 28 |  ;
 | 
|---|
| 29 |  ; What happened?
 | 
|---|
| 30 |  I $G(ZTSK)'>0 S RET(0)="-1^Failed to task" QUIT  ;->
 | 
|---|
| 31 |  S RET(0)=XWBHDL
 | 
|---|
| 32 |  D SETNODE^XWBDRPC(XWBHDL,"TASK",ZTSK)
 | 
|---|
| 33 |  ;
 | 
|---|
| 34 |  Q
 | 
|---|
| 35 |  ;
 | 
|---|
| 36 |  ;This is the Direct HL7 call point
 | 
|---|
| 37 | DIRECT(RET,LOC,RPC,RPCVER,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10)  ;Call a remote RPC
 | 
|---|
| 38 |  N X,I,INX,N,XWBHL7,XWBPAR,XWBPCNT,XWBDVER,XWBESSO,XWBHDL,PMAX
 | 
|---|
| 39 |  N XWBMSG,XWBSEC,RPCIEN
 | 
|---|
| 40 |  ;Protect caller from HL7
 | 
|---|
| 41 |  N HLMTIEN,HLDOM,HLECH,HLFS,HLINSTN,HLNEXT,HLNODE,HLPARAM,HLQ,HLQUIT
 | 
|---|
| 42 |  D SETUP(1) I $G(RET(1))'="" Q
 | 
|---|
| 43 |  ;(procedurename, query tag, error return, destination, Parameter array)
 | 
|---|
| 44 |  D DIRECT^XWB2HL7A("ZREMOTE RPC",XWBHDL,.XWBMSG,LOC,.XWBPAR)
 | 
|---|
| 45 |  I $P(XWBMSG,U,2) S RET(0)="-1^"_$P(XWBMSG,"^",3) Q
 | 
|---|
| 46 |  I 'HLMTIEN S RET(0)="-1^No Message returned" Q
 | 
|---|
| 47 |  D RETURN,RTNDATA^XWBDRPC(.RET,XWBHDL)
 | 
|---|
| 48 |  Q
 | 
|---|
| 49 |  ;
 | 
|---|
| 50 | SETUP(XWBDIR) ;Check/setup for HL7 call
 | 
|---|
| 51 |  S RET="",(XWBPAR,RPCIEN)="",XWBPCNT=0,XWBDVER=1,RPCVER=$G(RPCVER),PMAX=10
 | 
|---|
| 52 |  ;Check that user can access remote system with ESSO
 | 
|---|
| 53 |  S XWBESSO=$$GET^XUESSO1 I +XWBESSO<0 S RET(0)="",RET(1)=XWBESSO Q
 | 
|---|
| 54 |  ;Check that the link is setup.
 | 
|---|
| 55 |  I 'XWBDIR,'$$STAT^HLCSLM S RET(0)="",RET(1)="-1^Link Manager not running" Q
 | 
|---|
| 56 |  I '$$CHKLL^HLUTIL(LOC) S RET(0)="",RET(1)="-1^Link not setup" Q
 | 
|---|
| 57 |  ;Find local RPC here
 | 
|---|
| 58 |  S RPCIEN=$$RPCIEN^XWBLIB(RPC) I RPCIEN'>0 S RET(0)="",RET(1)="-1^No Local RPC" Q
 | 
|---|
| 59 |  F I=1:1:PMAX Q:'$D(@("P"_I))  S XWBPCNT=I
 | 
|---|
| 60 |  ;Get any security info.
 | 
|---|
| 61 |  S XWBSEC=3.14
 | 
|---|
| 62 |  ;Do parameter conversion
 | 
|---|
| 63 |  ;F IX=1:1:XWBPCNT I $G(^XWB(8994,RPCIEN,2,IX,2))]"" S N="P"_IX,X=@N,@(N_"=^(2)")
 | 
|---|
| 64 |  ;Build value to send
 | 
|---|
| 65 |  K XWBPAR S INX=1
 | 
|---|
| 66 |  F N="RPC","RPCVER","XWBPCNT","XWBESSO","XWBDVER","XWBSEC" D
 | 
|---|
| 67 |  . S XWBPAR(INX)=$$V2S(N)_$$V2S(@N),INX=INX+1
 | 
|---|
| 68 |  ;Load parameters into a string
 | 
|---|
| 69 |  F I=1:1:PMAX S N="P"_I Q:'$D(@N)  S X=$$LD(N),XWBPAR(INX)=X,INX=INX+1
 | 
|---|
| 70 |  ;Build a handle to link request with return.
 | 
|---|
| 71 |  S XWBHDL=$$HANDLE^XWBDRPC(),XWBMSG="" D ADDHDL^XWBDRPC(XWBHDL)
 | 
|---|
| 72 |  Q
 | 
|---|
| 73 |  ;
 | 
|---|
| 74 | LD(%V) ;Convert a var name into a transport string. Grabs from symbol table
 | 
|---|
| 75 |  N %1,%2,%3,%4
 | 
|---|
| 76 |  I $D(@%V)=1 Q $$V2S(%V)_$$V2S(@%V)
 | 
|---|
| 77 |  S %1=$S($D(@%V)#2:$$V2S(N)_$$V2S(@N),1:"")
 | 
|---|
| 78 |  F  S %V=$Q(@%V) Q:%V=""  S %3=$$V2S(%V),%4=$$V2S(@%V) S:$L(%1)+$L(%3)+$L(%4)>245 XWBPAR(INX)=%1,INX=INX+1,%1="" S %1=%1_%3_%4
 | 
|---|
| 79 |  Q %1
 | 
|---|
| 80 | V2S(V) ;Convert a value into L_value string
 | 
|---|
| 81 |  Q $E(1000+$L(V),2,4)_V
 | 
|---|
| 82 |  ;
 | 
|---|
| 83 | S2V(S) ;Convert a string L_value into a value
 | 
|---|
| 84 |  N D,L S L=+$E(S,1,3),D=""
 | 
|---|
| 85 |  S:L D=$E(S,4,3+L) S S=$E(S,4+L,999)
 | 
|---|
| 86 |  Q D
 | 
|---|
| 87 |  ;
 | 
|---|
| 88 | UD(%1) ;Unload strings into variables. Builds symbol table
 | 
|---|
| 89 |  N %
 | 
|---|
| 90 |  F  Q:%1=""  S %=$$S2V(.%1),@%=$$S2V(.%1)
 | 
|---|
| 91 |  Q
 | 
|---|
| 92 |  ;
 | 
|---|
| 93 |  ;This is called by HL7 to process a RPC on the remote system.
 | 
|---|
| 94 |  ;Call parameters 
 | 
|---|
| 95 |  ; 1. return the $NAME for the data
 | 
|---|
| 96 |  ; 2. query tag
 | 
|---|
| 97 |  ; 3. remote procedure name
 | 
|---|
| 98 |  ; 4. parameter array
 | 
|---|
| 99 | REMOTE(XWBY,XWBQT,XWBSPN,XWBPAR) ;Entry point on Remote system
 | 
|---|
| 100 |  ;XWBY is the return data
 | 
|---|
| 101 |  ;DUZ is NEWed to protect HL7
 | 
|---|
| 102 |  N %,I,X,Y,ERR,RPC,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,XWBPCNT,XWBDVER,XWBRPC
 | 
|---|
| 103 |  N RPC,RPCVER,XWBESSO,DUZ,$ESTACK,$ETRAP
 | 
|---|
| 104 |  N XWBA1,XWBA2,XWBA3,XWBA4,XWBA5,XWBA6,XWBA7,XWBA8,XWBA9,XWBA10
 | 
|---|
| 105 |  ;Set local error trap
 | 
|---|
| 106 |  S $ETRAP="D ETRAP^XWB2HL7"
 | 
|---|
| 107 |  ;See that leftover data in XUTL won't cause problems with %ZIS & HOME
 | 
|---|
| 108 |  K ^XUTL("XQ",$J,"IO")
 | 
|---|
| 109 |  ;Expand parameters into values
 | 
|---|
| 110 |  F I=1:1 Q:'$D(XWBPAR(I))  D UD(XWBPAR(I))
 | 
|---|
| 111 |  I '$D(RPC) S XWBY(0)="-1^Bad Message" G REX ;Bad msg
 | 
|---|
| 112 |  S XWBRPC=0,XWBRPC=$$RPCGET(RPC,.XWBRPC) I XWBRPC'>0 S XWBY(0)="-1^RPC name not found" G REX
 | 
|---|
| 113 |  I '$$RPCAVAIL^XWBLIB(XWBRPC,"R",RPCVER) S XWBY(0)="-1^RPC Access Blocked/Wrong Version at Remote Site" G REX
 | 
|---|
| 114 |  ;Check any security info.
 | 
|---|
| 115 |  ;I $D(XWBSEC),XWBSEC'=3.14 S XWBY(0)="-1^Invalid security" G REX
 | 
|---|
| 116 |  ;Check and Setup the user
 | 
|---|
| 117 |  D  I $G(XWBY(0))<0 G REX
 | 
|---|
| 118 |  . I XWBRPC("USER")=1 S DUZ=.5,DUZ(0)="" Q
 | 
|---|
| 119 |  . I '$$PUT^XUESSO1(XWBESSO) S XWBY(0)="-1^Bad User"
 | 
|---|
| 120 |  ;Enter in Sign-on log
 | 
|---|
| 121 |  D GETENV^%ZOSV S XWBSTATE("SLOG")=$$SLOG^XUS1($P(Y,U,2),,"",$P(Y,U),$P(Y,U,3),$P(XWBESSO,U,3),$P(XWBESSO,U,5))
 | 
|---|
| 122 |  ;Do parameter conversion
 | 
|---|
| 123 |  ;F IX=1:1:XWBPCNT I $G(^XWB(8994,XWBRPC,2,IX,3))]"" S N="P"_IX,X=@N,@(N_"=^(3)")
 | 
|---|
| 124 |  S PAR=$$PARAM
 | 
|---|
| 125 |  ;Save HL7 device
 | 
|---|
| 126 |  I $L($G(IO)) S IO(1,IO)="",IO(0)=IO D SAVDEV^%ZISUTL("HL7HOME")
 | 
|---|
| 127 |  ;Result returned in XWBY
 | 
|---|
| 128 |  D CAPI(XWBRPC("RTAG"),XWBRPC("RNAM"),PAR)
 | 
|---|
| 129 |  ;Restore HL7 Device
 | 
|---|
| 130 |  D USE^%ZISUTL("HL7HOME"),RMDEV^%ZISUTL("HL7HOME")
 | 
|---|
| 131 | REX ;Exit from remote.
 | 
|---|
| 132 |  ;What to do to data in XWBY for HL7 return.
 | 
|---|
| 133 |  K ^TMP("XWBR",$J)
 | 
|---|
| 134 |  I '$D(XWBY) S XWBY(0)="-1^Application failed to return any data"
 | 
|---|
| 135 |  I $D(XWBY)>9 D
 | 
|---|
| 136 |  . M ^TMP("XWBR",$J)=XWBY K XWBY S XWBY=$NA(^TMP("XWBR",$J))
 | 
|---|
| 137 |  I $D(XWBY)=1,$E(XWBY)'="^" D
 | 
|---|
| 138 |  . S ^TMP("XWBR",$J,0)=XWBY K XWBY S XWBY=$NA(^TMP("XWBR",$J))
 | 
|---|
| 139 |  ;If XWBY is a $NA value just return it.
 | 
|---|
| 140 |  I $D(XWBSTATE("SLOG")) D LOUT^XUSCLEAN(XWBSTATE("SLOG"))
 | 
|---|
| 141 |  Q
 | 
|---|
| 142 |  ;
 | 
|---|
| 143 | CAPI(TAG,NAM,PAR) ;make API call
 | 
|---|
| 144 |  ;DUZ was setup in Remote
 | 
|---|
| 145 |  N HL,HLA,HLERR,HLL,HLMTIENS,IO,R,$ES,$ET
 | 
|---|
| 146 |  S $ET="D CAPIER^XWB2HL7"
 | 
|---|
| 147 |  S R=TAG_"^"_NAM_"(.XWBY"_$S(PAR="":")",1:","_PAR_")")
 | 
|---|
| 148 |  ;Ready to call RPC?  Setup the Null device
 | 
|---|
| 149 |  S IOP="NULL",%ZIS="H0N" D ^%ZIS
 | 
|---|
| 150 |  D @R
 | 
|---|
| 151 |  ;Close the NULL device
 | 
|---|
| 152 |  S IO("C")=1 D ^%ZISC
 | 
|---|
| 153 |  ;Return data is in XWBY.
 | 
|---|
| 154 |  Q
 | 
|---|
| 155 |  ;
 | 
|---|
| 156 | CAPIER ;Handle a error in called RPC
 | 
|---|
| 157 |  S XWBY(0)="-1^Remote Error: "_$E($$EC^%ZOSV,1,200) ;Grab the error first
 | 
|---|
| 158 |  D ^%ZTER ;record
 | 
|---|
| 159 |  S IO("C")=1 D ^%ZISC ;Close the NULL device
 | 
|---|
| 160 |  D UNWIND^%ZTER ;Unwind stack and return to HL7
 | 
|---|
| 161 |  Q
 | 
|---|
| 162 |  ;
 | 
|---|
| 163 | RETURN ;This tag is called by HL7 when the data returns from the remote system
 | 
|---|
| 164 |  ;Need to get the MSG id that we added so we know where to place the
 | 
|---|
| 165 |  ;results. Set in XWB RPC SERVER SEND protocol.
 | 
|---|
| 166 |  N $ES,$ETRAP S $ETRAP="D ^%ZTER D UNWIND^%ZTER"
 | 
|---|
| 167 |  N XWBHDL,XWB1,XWB2,I,J,X
 | 
|---|
| 168 |  Q:'$D(HLNEXT)
 | 
|---|
| 169 |  ;Now to find the MSA line
 | 
|---|
| 170 |  F I=1:1 X HLNEXT Q:HLQUIT'>0  S X(I)=HLNODE Q:"MSA"=$E(HLNODE,1,3)
 | 
|---|
| 171 |  I HLNODE'["MSA" Q  ;Something wrong
 | 
|---|
| 172 |  I $P(HLNODE,U,2)'="AA" G REJECT
 | 
|---|
| 173 |  ;Now to find the QAK line
 | 
|---|
| 174 |  F I=I+1:1 X HLNEXT Q:HLQUIT'>0  S X(I)=HLNODE Q:"QAK"=$E(HLNODE,1,3)
 | 
|---|
| 175 |  I HLNODE'["QAK" Q  ;Something wrong
 | 
|---|
| 176 |  ;Get the handle
 | 
|---|
| 177 |  S XWBHDL=$P(HLNODE,"^",2)
 | 
|---|
| 178 |  Q:$$CHKHDL^XWBDRPC(XWBHDL)["-1"  ;XTMP missing
 | 
|---|
| 179 |  ;Now to place the data
 | 
|---|
| 180 |  F I=1:1 X HLNEXT Q:HLQUIT'>0  D:$E(HLNODE,1,3)="RDT"
 | 
|---|
| 181 |  . S X=$E(HLNODE,5,999),J=0 F  S J=$O(HLNODE(J)) Q:'J  S X=X_HLNODE(J)
 | 
|---|
| 182 |  . D PLACE(XWBHDL,X)
 | 
|---|
| 183 |  . Q
 | 
|---|
| 184 |  ;
 | 
|---|
| 185 |  S X=$$HDLSTA^XWBDRPC(XWBHDL,"1^Done")
 | 
|---|
| 186 |  Q
 | 
|---|
| 187 |  ;
 | 
|---|
| 188 | REJECT ;Handle some kind of reject on remote system
 | 
|---|
| 189 |  N HDL,MID,MSG,X
 | 
|---|
| 190 |  S HDL="XWBDRPC",MID=$P(HLNODE,U,3),MSG="-1^"_$P(HLNODE,U,4) ;Save reason
 | 
|---|
| 191 |  F  S HDL=$O(^XTMP(HDL)),X="" Q:HDL'["XWBDRPC"  S X=$$GETNODE^XWBDRPC(HDL,"MSGID") Q:X=MID
 | 
|---|
| 192 |  Q:X=""  ;Didn't find Handle
 | 
|---|
| 193 |  S X=$$HDLSTA^XWBDRPC(HDL,MSG)
 | 
|---|
| 194 |  Q
 | 
|---|
| 195 |  ;
 | 
|---|
| 196 | PLACE(HL,DATA) ;Called by HL7 to place each line of data.
 | 
|---|
| 197 |  N IX
 | 
|---|
| 198 |  S IX=+$G(^XTMP(HL,"CNT")),^XTMP(HL,"D",IX)=DATA,^XTMP(HL,"CNT")=IX+1
 | 
|---|
| 199 |  Q
 | 
|---|
| 200 |  ;
 | 
|---|
| 201 | RPCGET(N,R) ;Convert RPC name to IEN and parameters.
 | 
|---|
| 202 |  N T,T0
 | 
|---|
| 203 |  S T=$G(N) Q:T="" "-1^No RPC name"
 | 
|---|
| 204 |  S T=$$RPCIEN^XWBLIB(T) Q:T'>0 "-1^Bad RPC name"
 | 
|---|
| 205 |  Q:'$D(R) T
 | 
|---|
| 206 |  S T0=$G(^XWB(8994,T,0)),R("IEN")=T,R("NAME")=$P(T0,"^")
 | 
|---|
| 207 |  S R("RTAG")=$P(T0,"^",2),R("RNAM")=$P(T0,"^",3)
 | 
|---|
| 208 |  S R("XWBPTYPE")=$P(T0,"^",4),R("XWBWRAP")=$P(T0,"^",8),R("USER")=$P(T0,"^",10)
 | 
|---|
| 209 |  ;S XWBPCNT=0 F I=0:0 S I=$O(^XWB(8994,T,1,I)) Q:I'>0  S XWBPCNT=XWBPCNT+1
 | 
|---|
| 210 |  Q T
 | 
|---|
| 211 | PARAM() ;Build remote parameter list
 | 
|---|
| 212 |  N I,%,X,A S X=""
 | 
|---|
| 213 |  F I=1:1:XWBPCNT S %="P"_I,A="XWBA"_I Q:'$D(@%)  K @A D
 | 
|---|
| 214 |  . I $D(@%)=1 S X=X_%_"," Q
 | 
|---|
| 215 |  . S X=X_"."_A_"," M @A=@% Q
 | 
|---|
| 216 |  Q $E(X,1,$L(X)-1)
 | 
|---|
| 217 |  ;
 | 
|---|
| 218 |  ;
 | 
|---|
| 219 | RPCCHK(RET,HDL) ;RPC call to check a handle status
 | 
|---|
| 220 |  N S,M,Z
 | 
|---|
| 221 |  I $G(HDL)="" S RET(0)="-1^Bad Handle" Q
 | 
|---|
| 222 |  S RET(0)=$$CHKHDL^XWBDRPC(HDL),S=$$GETNODE(HDL,"MSGID")
 | 
|---|
| 223 |  I RET(0)'["Done",$L(S) D  S $P(RET(1),"^",3)=Z
 | 
|---|
| 224 |  . S RET(1)=$$MSGSTAT^HLUTIL(S),M=+RET(1),Z=""
 | 
|---|
| 225 |  . I M=1 S Z=$S($P(RET(1),"^",5)>1:"NOT first in queue",1:"First in queue")
 | 
|---|
| 226 |  . I M=1.5 S Z="Opening connection"_$S($P(RET(1),"^",6):", open failed "_$P(RET(1),"^",6)_" times.",1:"")
 | 
|---|
| 227 |  . I M=1.7 S Z="Sent, awaiting responce"
 | 
|---|
| 228 |  . I M=2 S Z="Awaiting application ACK"
 | 
|---|
| 229 |  Q
 | 
|---|
| 230 |  ;
 | 
|---|
| 231 | GETNODE(%1,%2) ;Pass to XWBDRPC
 | 
|---|
| 232 |  Q $$GETNODE^XWBDRPC(%1,%2)
 | 
|---|
| 233 |  ;
 | 
|---|
| 234 | ETRAP ;Handle errors in the RPC at the remote site.
 | 
|---|
| 235 |  K ^TMP("XWBR",$J),XWBY
 | 
|---|
| 236 |  S ^TMP("XWBR",$J,0)="-1^Trapped Error at remote site.  "_$$EC^%ZOSV,XWBY=$NA(^TMP("XWBR",$J))
 | 
|---|
| 237 |  S XWBY=$NA(^TMP("XWBR",$J)) ;Setup the return data.
 | 
|---|
| 238 |  ;Record the error, and exit to caller
 | 
|---|
| 239 |  D ^%ZTER,UNWIND^%ZTER
 | 
|---|
| 240 |  Q
 | 
|---|