INHUSEQ ;DGH; 6 Dec 94 12:41;SEQuence number protocol functions
;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
;COPYRIGHT 1991-2000 SAIC
;
SEQOUT(INUIF,INERR) ;Process outbound messages under seq # protocol.
;INPUT:
; INUIF = (req) entry in INTHU
; INERR = (opt) error message array (Pass by reference)
;OUTPUT:
; 0=success 1=error 2=fatal error
N SEQ,X,DEST
S DEST=$P($G(^INTHU(INUIF,0)),U,2)
I 'DEST S ERR="No destination specified in UIF for message "_MESSID Q 2
I '$D(^INRHD(DEST)) S ERR="Destination does not exist for message "_MESSID Q 2
;Determine if seq. # protocol is in effect--If .09 field is not 1,
;no need to assign seq. no.
Q:'$P(^INRHD(DEST,0),U,9) 0
F I=1:1:5 L +^INRHD(DEST,3):3 Q:$T
I '$T S ERR="Lock failed on LAST SEQUENCE NUMBER field for destination "_$P(^INRHD(DEST,0),U)_" for "_MESSID Q 1
S SEQ=$P($G(^INRHD(DEST,3)),U)+1
;Stuff sequence number in MSH of uif entry
S X=$$FORMAT(INUIF,SEQ,.INERR)
I 'X S $P(^INRHD(DEST,3),U)=SEQ
L -^INRHD(DEST,3)
Q X
;
;
FORMAT(UIF,SEQ,INERR) ;Entry point to add a SEQuence number to the MSH
;and to the SEQUENCE NUMBER field of an entry in INTHU(UIF
;INPUT:
;--UIF=ien in Universal Interface File
;--SEQ=seqence number to be inserted in the MSH segment of the message
;--INERR (opt)=array in which to place any error messages
;OUTPUT: 0=sucessful update, 2=unsuccessful update (fatal)
;LOCAL:
;--MSH0 = Base message MSH segment. May be an array
;--MSH = New MSH w SEQ inserted. Array may be one node larger than MSH0
;
N C,CP,I,INDELIM,INSMIN,INV,INVS,L,LCT,MSH,MSH0,CNT,DIF,CPSEQ
;---Store original MSH in MSH0
S LCT=0 D GETLINE^INHOU(UIF,.LCT,.MSH0)
I $E(MSH0,1,3)'="MSH" S INERR="Error in FORMAT^INHUSEQ. No MSH segment in message "_UIF Q 2
S INDELIM=$E(MSH0,4)
;Create string of first 12 pieces, insert sequence # in 13, then
;string out remaining pieces.
S CPSEQ=13,CP=CPSEQ-1,MSH=$P(MSH0,INDELIM,1,CP)
S CNT=$L(MSH0,INDELIM)
I $D(MSH0)>9 F I=1:1 Q:'$D(MSH0(I)) S CNT=CNT+$L(MSH0(I),INDELIM)
S I=CPSEQ,L=SEQ D SETPIECE^INHU(.MSH,INDELIM,I,L,.CP)
F I=CPSEQ+1:1:CNT S L=$$PIECE^INHU(.MSH0,INDELIM,I) D SETPIECE^INHU(.MSH,INDELIM,I,L,.CP)
;If the number of overflow nodes DIFfers from old MSH0 and new MSH...
S DIF=$O(MSH(""),-1)-$O(MSH0(""),-1) I 'DIF D MSH,XREF Q 0
;
;Unless the addition of SEQ has created an overflow node, the following
;will not occur.
;Store message body in array and reformat entire entry in UIF
K ^UTILITY("INV",$J)
S INVS=$P(^INRHSITE(1,0),U,12),INV=$S(INVS<2:"INV",1:"^UTILITY(""INV"",$J)")
S INSMIN=$S($P($G(^INRHSITE(1,0)),U,14):$P(^(0),U,14),1:2500)
;Place new MSH at top of new array
S C=1,@INV@(C)=MSH
I $D(MSH)>9 F Q:'$D(MSH(C)) S C=C+1,@INV@(C)=MSH(C-1)
S @INV@(C)=@INV@(C)_"|CR|"
;If overflow node(s) created, lines in ^INTHU will "move" DIF
F S LCT=$O(^INTHU(UIF,3,LCT)) Q:'LCT D
.S @INV@(LCT+DIF)=^INTHU(UIF,3,LCT,0)
.D:'INVS MC^INHS
K ^INTHU(UIF,3)
;Store data from global INV
S C=0 F S C=$O(@INV@(C)) Q:'C S ^INTHU(UIF,3,C,0)=@INV@(C),L=C
S ^INTHU(UIF,3,0)="^^"_L_"^"_L
D XREF
Q 0
;
MSH ;Store replacement MSH with overflow nodes if needed
I $D(MSH)<10 S ^INTHU(UIF,3,1,0)=MSH_"|CR|" Q
S ^INTHU(UIF,3,1,0)=MSH
F I=1:1 Q:'$D(MSH(I)) S C=I+1,^INTHU(UIF,3,C,0)=MSH(I)
S ^INTHU(UIF,3,C,0)=^(0)_"|CR|"
Q
;
XREF ;Store SEQ in .17 field and set x-ref.
S $P(^INTHU(UIF,0),U,17)=SEQ,^INTHU("ASEQ",DEST,SEQ,UIF)=""
Q
;
SEQIN(INDSTR,INSEQ,STAT,TXT,EXPCT) ;Process incoming sequenced messages.
;This will verify sequence number and set variables
;needed for accept ack. It does not send the ack.
;VARIABLES
; INDSTR = Entry in Interface Destination File
; INSEQ = Sequence number (piece 13 of MSH) (pass by reference)
; This may be reset to 0 within this tag. SEQ is later stored
; in LAST SEQUENCE NUMBER field of the Int. Dest. File.
; STAT = Status to include in ack (PBR)
; TXT = Message text to include in ack (PBR)
; EXPCT = Expected sequence number for ack (PBR)
;OUTPUT:
; 0=success 1=non-fatal error
;INSEQ=0 indicates start or restart
I INSEQ=0 D Q 0
.I '$G(^INRHD(INDSTR,3)) S STAT="CA",TXT="Starting link",EXPCT=-1 Q
.S STAT="CA",TXT="Re-starting link",EXPCT=1+^INRHD(INDSTR,3)
;INSEQ=-1 indicates re-synch. Receiver will need to reset LAST SENT to 0
I INSEQ=-1 S INEQ=0,STAT="CA",TXT="Synchronizing link",EXPCT=-1 Q 0
;Else sequence is greater than 0
I '$D(^INRHD(INDSTR,3)) S STAT="CA",TXT="Link is not initialized",EXPCT="" Q 1
S EXPCT=1+^INRHD(INDSTR,3)
I INSEQ=EXPCT S STAT="CA",TXT="" Q 0
;else sequence number is incorrect
S STAT="CR",TXT="Out of sequence" Q 1
;
ACKINSEQ(MSASTAT,INDSTR,EXPCT,INSEND,INERR) ;Process incoming app ack
;under seq # protocol
;INPUT
;--MSASTAT = CA,CE,CR
;--INDSTR = ien of entry in Int. Dest. File.
;--EXPCT = Expected sequence number from MSA segment from other system.
;--INSEND = Variable to contain ien(s) of previously-sent messages
; which must be resent to match EXPCT. (PBR)
; Format of array is INSEND(SEQ)=UIF
;--INERR = variable to contain error array (PBR)
;RETURN
;0 = ok 3 = out of synch
N SEQ,LAST
I MSASTAT["CA" Q 0
I EXPCT=1+^INRHD(INDSTR,3) Q 0
I EXPCT>1+^INRHD(INDSTR,3) S INVL=1,INERR="Expected sequence number is higher than current" Q 3
;else EXPCT<1, so EXPCT is a previously sent message. Find ien of that
;entry so it can be resent, and reque all subsequent entries.
I '$D(^INTHU("ASEQ",INDSTR,EXPCT)) S INERR="Can not locate expected message "_EXPCT Q 3
S INSEND=$O(^INTHU("ASEQ",INDSTR,EXPCT,"")) I 'INSEND S INERR="Can not locate expected message "_EXPCT Q 3
S SEQ=EXPCT,LAST=+^INRHD(INSTR,3)
;create array of all values between last sent and expected.
;Note: current HL7 spec indicates there will not be more than one
;entry in this array (ie resend only the last message).
F I=1:1 S SEQ=$O(^INTHU("ASEQ",INDSTR,SEQ)) Q:SEQ'<LAST!'SEQ S INSEND(SEQ)=$O(^INTHU("ASEQ",INDSTR,EXPCT,""))
Q 0
;
INHUSEQ ;DGH; 6 Dec 94 12:41;SEQuence number protocol functions
+1 ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
+2 ;COPYRIGHT 1991-2000 SAIC
+3 ;
SEQOUT(INUIF,INERR) ;Process outbound messages under seq # protocol.
+1 ;INPUT:
+2 ; INUIF = (req) entry in INTHU
+3 ; INERR = (opt) error message array (Pass by reference)
+4 ;OUTPUT:
+5 ; 0=success 1=error 2=fatal error
+6 NEW SEQ,X,DEST
+7 SET DEST=$PIECE($GET(^INTHU(INUIF,0)),U,2)
+8 IF 'DEST
SET ERR="No destination specified in UIF for message "_MESSID
QUIT 2
+9 IF '$DATA(^INRHD(DEST))
SET ERR="Destination does not exist for message "_MESSID
QUIT 2
+10 ;Determine if seq. # protocol is in effect--If .09 field is not 1,
+11 ;no need to assign seq. no.
+12 IF '$PIECE(^INRHD(DEST,0),U,9)
QUIT 0
+13 FOR I=1:1:5
LOCK +^INRHD(DEST,3):3
IF $TEST
QUIT
+14 IF '$TEST
SET ERR="Lock failed on LAST SEQUENCE NUMBER field for destination "_$PIECE(^INRHD(DEST,0),U)_" for "_MESSID
QUIT 1
+15 SET SEQ=$PIECE($GET(^INRHD(DEST,3)),U)+1
+16 ;Stuff sequence number in MSH of uif entry
+17 SET X=$$FORMAT(INUIF,SEQ,.INERR)
+18 IF 'X
SET $PIECE(^INRHD(DEST,3),U)=SEQ
+19 LOCK -^INRHD(DEST,3)
+20 QUIT X
+21 ;
+22 ;
FORMAT(UIF,SEQ,INERR) ;Entry point to add a SEQuence number to the MSH
+1 ;and to the SEQUENCE NUMBER field of an entry in INTHU(UIF
+2 ;INPUT:
+3 ;--UIF=ien in Universal Interface File
+4 ;--SEQ=seqence number to be inserted in the MSH segment of the message
+5 ;--INERR (opt)=array in which to place any error messages
+6 ;OUTPUT: 0=sucessful update, 2=unsuccessful update (fatal)
+7 ;LOCAL:
+8 ;--MSH0 = Base message MSH segment. May be an array
+9 ;--MSH = New MSH w SEQ inserted. Array may be one node larger than MSH0
+10 ;
+11 NEW C,CP,I,INDELIM,INSMIN,INV,INVS,L,LCT,MSH,MSH0,CNT,DIF,CPSEQ
+12 ;---Store original MSH in MSH0
+13 SET LCT=0
DO GETLINE^INHOU(UIF,.LCT,.MSH0)
+14 IF $EXTRACT(MSH0,1,3)'="MSH"
SET INERR="Error in FORMAT^INHUSEQ. No MSH segment in message "_UIF
QUIT 2
+15 SET INDELIM=$EXTRACT(MSH0,4)
+16 ;Create string of first 12 pieces, insert sequence # in 13, then
+17 ;string out remaining pieces.
+18 SET CPSEQ=13
SET CP=CPSEQ-1
SET MSH=$PIECE(MSH0,INDELIM,1,CP)
+19 SET CNT=$LENGTH(MSH0,INDELIM)
+20 IF $DATA(MSH0)>9
FOR I=1:1
IF '$DATA(MSH0(I))
QUIT
SET CNT=CNT+$LENGTH(MSH0(I),INDELIM)
+21 SET I=CPSEQ
SET L=SEQ
DO SETPIECE^INHU(.MSH,INDELIM,I,L,.CP)
+22 FOR I=CPSEQ+1:1:CNT
SET L=$$PIECE^INHU(.MSH0,INDELIM,I)
DO SETPIECE^INHU(.MSH,INDELIM,I,L,.CP)
+23 ;If the number of overflow nodes DIFfers from old MSH0 and new MSH...
+24 SET DIF=$ORDER(MSH(""),-1)-$ORDER(MSH0(""),-1)
IF 'DIF
DO MSH
DO XREF
QUIT 0
+25 ;
+26 ;Unless the addition of SEQ has created an overflow node, the following
+27 ;will not occur.
+28 ;Store message body in array and reformat entire entry in UIF
+29 KILL ^UTILITY("INV",$JOB)
+30 SET INVS=$PIECE(^INRHSITE(1,0),U,12)
SET INV=$SELECT(INVS<2:"INV",1:"^UTILITY(""INV"",$J)")
+31 SET INSMIN=$SELECT($PIECE($GET(^INRHSITE(1,0)),U,14):$PIECE(^(0),U,14),1:2500)
+32 ;Place new MSH at top of new array
+33 SET C=1
SET @INV@(C)=MSH
+34 IF $DATA(MSH)>9
FOR
IF '$DATA(MSH(C))
QUIT
SET C=C+1
SET @INV@(C)=MSH(C-1)
+35 SET @INV@(C)=@INV@(C)_"|CR|"
+36 ;If overflow node(s) created, lines in ^INTHU will "move" DIF
+37 FOR
SET LCT=$ORDER(^INTHU(UIF,3,LCT))
IF 'LCT
QUIT
Begin DoDot:1
+38 SET @INV@(LCT+DIF)=^INTHU(UIF,3,LCT,0)
+39 IF 'INVS
DO MC^INHS
End DoDot:1
+40 KILL ^INTHU(UIF,3)
+41 ;Store data from global INV
+42 SET C=0
FOR
SET C=$ORDER(@INV@(C))
IF 'C
QUIT
SET ^INTHU(UIF,3,C,0)=@INV@(C)
SET L=C
+43 SET ^INTHU(UIF,3,0)="^^"_L_"^"_L
+44 DO XREF
+45 QUIT 0
+46 ;
MSH ;Store replacement MSH with overflow nodes if needed
+1 IF $DATA(MSH)<10
SET ^INTHU(UIF,3,1,0)=MSH_"|CR|"
QUIT
+2 SET ^INTHU(UIF,3,1,0)=MSH
+3 FOR I=1:1
IF '$DATA(MSH(I))
QUIT
SET C=I+1
SET ^INTHU(UIF,3,C,0)=MSH(I)
+4 SET ^INTHU(UIF,3,C,0)=^(0)_"|CR|"
+5 QUIT
+6 ;
XREF ;Store SEQ in .17 field and set x-ref.
+1 SET $PIECE(^INTHU(UIF,0),U,17)=SEQ
SET ^INTHU("ASEQ",DEST,SEQ,UIF)=""
+2 QUIT
+3 ;
SEQIN(INDSTR,INSEQ,STAT,TXT,EXPCT) ;Process incoming sequenced messages.
+1 ;This will verify sequence number and set variables
+2 ;needed for accept ack. It does not send the ack.
+3 ;VARIABLES
+4 ; INDSTR = Entry in Interface Destination File
+5 ; INSEQ = Sequence number (piece 13 of MSH) (pass by reference)
+6 ; This may be reset to 0 within this tag. SEQ is later stored
+7 ; in LAST SEQUENCE NUMBER field of the Int. Dest. File.
+8 ; STAT = Status to include in ack (PBR)
+9 ; TXT = Message text to include in ack (PBR)
+10 ; EXPCT = Expected sequence number for ack (PBR)
+11 ;OUTPUT:
+12 ; 0=success 1=non-fatal error
+13 ;INSEQ=0 indicates start or restart
+14 IF INSEQ=0
Begin DoDot:1
+15 IF '$GET(^INRHD(INDSTR,3))
SET STAT="CA"
SET TXT="Starting link"
SET EXPCT=-1
QUIT
+16 SET STAT="CA"
SET TXT="Re-starting link"
SET EXPCT=1+^INRHD(INDSTR,3)
End DoDot:1
QUIT 0
+17 ;INSEQ=-1 indicates re-synch. Receiver will need to reset LAST SENT to 0
+18 IF INSEQ=-1
SET INEQ=0
SET STAT="CA"
SET TXT="Synchronizing link"
SET EXPCT=-1
QUIT 0
+19 ;Else sequence is greater than 0
+20 IF '$DATA(^INRHD(INDSTR,3))
SET STAT="CA"
SET TXT="Link is not initialized"
SET EXPCT=""
QUIT 1
+21 SET EXPCT=1+^INRHD(INDSTR,3)
+22 IF INSEQ=EXPCT
SET STAT="CA"
SET TXT=""
QUIT 0
+23 ;else sequence number is incorrect
+24 SET STAT="CR"
SET TXT="Out of sequence"
QUIT 1
+25 ;
ACKINSEQ(MSASTAT,INDSTR,EXPCT,INSEND,INERR) ;Process incoming app ack
+1 ;under seq # protocol
+2 ;INPUT
+3 ;--MSASTAT = CA,CE,CR
+4 ;--INDSTR = ien of entry in Int. Dest. File.
+5 ;--EXPCT = Expected sequence number from MSA segment from other system.
+6 ;--INSEND = Variable to contain ien(s) of previously-sent messages
+7 ; which must be resent to match EXPCT. (PBR)
+8 ; Format of array is INSEND(SEQ)=UIF
+9 ;--INERR = variable to contain error array (PBR)
+10 ;RETURN
+11 ;0 = ok 3 = out of synch
+12 NEW SEQ,LAST
+13 IF MSASTAT["CA"
QUIT 0
+14 IF EXPCT=1+^INRHD(INDSTR,3)
QUIT 0
+15 IF EXPCT>1+^INRHD(INDSTR,3)
SET INVL=1
SET INERR="Expected sequence number is higher than current"
QUIT 3
+16 ;else EXPCT<1, so EXPCT is a previously sent message. Find ien of that
+17 ;entry so it can be resent, and reque all subsequent entries.
+18 IF '$DATA(^INTHU("ASEQ",INDSTR,EXPCT))
SET INERR="Can not locate expected message "_EXPCT
QUIT 3
+19 SET INSEND=$ORDER(^INTHU("ASEQ",INDSTR,EXPCT,""))
IF 'INSEND
SET INERR="Can not locate expected message "_EXPCT
QUIT 3
+20 SET SEQ=EXPCT
SET LAST=+^INRHD(INSTR,3)
+21 ;create array of all values between last sent and expected.
+22 ;Note: current HL7 spec indicates there will not be more than one
+23 ;entry in this array (ie resend only the last message).
+24 FOR I=1:1
SET SEQ=$ORDER(^INTHU("ASEQ",INDSTR,SEQ))
IF SEQ'<LAST!'SEQ
QUIT
SET INSEND(SEQ)=$ORDER(^INTHU("ASEQ",INDSTR,EXPCT,""))
+25 QUIT 0
+26 ;