[613] | 1 | MHV7U ;WAS/GPM - HL7 UTILITIES ; [1/7/08 10:21pm]
|
---|
| 2 | ;;1.0;My HealtheVet;**1,2**;Aug 23, 2005;Build 22
|
---|
| 3 | ;;Per VHA Directive 2004-038, this routine should not be modified.
|
---|
| 4 | ;
|
---|
| 5 | ;This routine contains generic utilities used when building
|
---|
| 6 | ;or processing HL7 messages.
|
---|
| 7 | ;
|
---|
| 8 | Q ;Direct entry not supported
|
---|
| 9 | ;
|
---|
| 10 | LOADMSG(MSGROOT) ; Load HL7 message into temporary global for processing
|
---|
| 11 | ;
|
---|
| 12 | ;This subroutine assumes that all VistA HL7 environment variables are
|
---|
| 13 | ;properly initialized and will produce a fatal error if they aren't.
|
---|
| 14 | ;
|
---|
| 15 | N CNT,SEG
|
---|
| 16 | K @MSGROOT
|
---|
| 17 | F SEG=1:1 X HLNEXT Q:HLQUIT'>0 D
|
---|
| 18 | . S CNT=0
|
---|
| 19 | . S @MSGROOT@(SEG,CNT)=HLNODE
|
---|
| 20 | . F S CNT=$O(HLNODE(CNT)) Q:'CNT S @MSGROOT@(SEG,CNT)=HLNODE(CNT)
|
---|
| 21 | Q
|
---|
| 22 | ;
|
---|
| 23 | LOADXMT(XMT) ;Set HL dependent XMT values
|
---|
| 24 | ;
|
---|
| 25 | ; The HL array and variables are expected to be defined. If not,
|
---|
| 26 | ; message processing will fail. These references should not be
|
---|
| 27 | ; wrapped in $G, as null values will simply postpone the failure to
|
---|
| 28 | ; a point that will be harder to diagnose. Except HL("APAT") which
|
---|
| 29 | ; is not defined on synchronous calls.
|
---|
| 30 | ; Also assumes MHV RESPONSE MAP file is setup for every protocol
|
---|
| 31 | ; pair defined by MHV package.
|
---|
| 32 | ;
|
---|
| 33 | ; Integration Agreements:
|
---|
| 34 | ; 1373 : Reference to PROTOCOL file #101
|
---|
| 35 | ;
|
---|
| 36 | N SUBPROT,RESPIEN,RESP0
|
---|
| 37 | S XMT("MID")=HL("MID") ;Message ID
|
---|
| 38 | S XMT("MODE")="A" ;Response mode
|
---|
| 39 | I $G(HL("APAT"))="" S XMT("MODE")="S" ;Synchronous mode
|
---|
| 40 | S XMT("HLMTIENS")=HLMTIENS ;Message IEN
|
---|
| 41 | S XMT("MESSAGE TYPE")=HL("MTN") ;Message type
|
---|
| 42 | S XMT("EVENT TYPE")=HL("ETN") ;Event type
|
---|
| 43 | S XMT("DELIM")=HL("FS")_HL("ECH") ;HL Delimiters
|
---|
| 44 | S XMT("MAX SIZE")=0 ;Default size unlimited
|
---|
| 45 | ;
|
---|
| 46 | ; Map response protocol and builder
|
---|
| 47 | S SUBPROT=$P(^ORD(101,HL("EIDS"),0),"^")
|
---|
| 48 | S RESPIEN=$O(^MHV(2275.4,"B",SUBPROT,0))
|
---|
| 49 | S RESP0=$G(^MHV(2275.4,RESPIEN,0))
|
---|
| 50 | S XMT("PROTOCOL")=$P(RESP0,"^",2) ;Response Protocol
|
---|
| 51 | S XMT("BUILDER")=$TR($P(RESP0,"^",3),"~","^") ;Response Builder
|
---|
| 52 | S XMT("BREAK SEGMENT")=$P(RESP0,"^",4) ;Boundary Segment
|
---|
| 53 | Q
|
---|
| 54 | ;
|
---|
| 55 | DELIM(PROTOCOL) ;Return string of message delimiters based on Protocol
|
---|
| 56 | ;
|
---|
| 57 | ; Integration Agreements:
|
---|
| 58 | ; 2161 : INIT^HLFNC2
|
---|
| 59 | ;
|
---|
| 60 | N HL
|
---|
| 61 | Q:PROTOCOL="" ""
|
---|
| 62 | D INIT^HLFNC2(PROTOCOL,.HL)
|
---|
| 63 | Q $G(HL("FS"))_$G(HL("ECH"))
|
---|
| 64 | ;
|
---|
| 65 | PARSEMSG(MSGROOT,HL) ; Message Parser
|
---|
| 66 | ; Does not handle segments that span nodes
|
---|
| 67 | ; Does not handle extremely long segments (uses a local)
|
---|
| 68 | ; Does not handle long fields (segment parser doesn't)
|
---|
| 69 | ;
|
---|
| 70 | N SEG,CNT,DATA,MSG
|
---|
| 71 | F CNT=1:1 Q:'$D(@MSGROOT@(CNT)) M SEG=@MSGROOT@(CNT) D
|
---|
| 72 | . D PARSESEG(SEG(0),.DATA,.HL)
|
---|
| 73 | . K @MSGROOT@(CNT)
|
---|
| 74 | . I DATA(0)'="" M @MSGROOT@(CNT)=DATA
|
---|
| 75 | . Q:'$D(SEG(1))
|
---|
| 76 | . ;Add handler for segments that span nodes here.
|
---|
| 77 | . Q
|
---|
| 78 | Q
|
---|
| 79 | ;
|
---|
| 80 | PARSESEG(SEG,DATA,HL) ;Generic segment parser
|
---|
| 81 | ;This procedure parses a single HL7 segment and builds an array
|
---|
| 82 | ;subscripted by the field number containing the data for that field.
|
---|
| 83 | ; Does not handle segments that span nodes
|
---|
| 84 | ;
|
---|
| 85 | ; Input:
|
---|
| 86 | ; SEG - HL7 segment to parse
|
---|
| 87 | ; HL - HL7 environment array
|
---|
| 88 | ;
|
---|
| 89 | ; Output:
|
---|
| 90 | ; Function value - field data array [SUB1:field, SUB2:repetition,
|
---|
| 91 | ; SUB3:component, SUB4:sub-component]
|
---|
| 92 | ;
|
---|
| 93 | N CMP ;component subscript
|
---|
| 94 | N CMPVAL ;component value
|
---|
| 95 | N FLD ;field subscript
|
---|
| 96 | N FLDVAL ;field value
|
---|
| 97 | N REP ;repetition subscript
|
---|
| 98 | N REPVAL ;repetition value
|
---|
| 99 | N SUB ;sub-component subscript
|
---|
| 100 | N SUBVAL ;sub-component value
|
---|
| 101 | N FS ;field separator
|
---|
| 102 | N CS ;component separator
|
---|
| 103 | N RS ;repetition separator
|
---|
| 104 | N SS ;sub-component separator
|
---|
| 105 | ;
|
---|
| 106 | K DATA
|
---|
| 107 | S FS=HL("FS")
|
---|
| 108 | S CS=$E(HL("ECH"))
|
---|
| 109 | S RS=$E(HL("ECH"),2)
|
---|
| 110 | S SS=$E(HL("ECH"),4)
|
---|
| 111 | ;
|
---|
| 112 | S DATA(0)=$P(SEG,FS)
|
---|
| 113 | S SEG=$P(SEG,FS,2,9999)
|
---|
| 114 | F FLD=1:1:$L(SEG,FS) D
|
---|
| 115 | . S FLDVAL=$P(SEG,FS,FLD)
|
---|
| 116 | . F REP=1:1:$L(FLDVAL,RS) D
|
---|
| 117 | . . S REPVAL=$P(FLDVAL,RS,REP)
|
---|
| 118 | . . I REPVAL[CS F CMP=1:1:$L(REPVAL,CS) D
|
---|
| 119 | . . . S CMPVAL=$P(REPVAL,CS,CMP)
|
---|
| 120 | . . . I CMPVAL[SS F SUB=1:1:$L(CMPVAL,SS) D
|
---|
| 121 | . . . . S SUBVAL=$P(CMPVAL,SS,SUB)
|
---|
| 122 | . . . . I SUBVAL'="" S DATA(FLD,REP,CMP,SUB)=SUBVAL
|
---|
| 123 | . . . I '$D(DATA(FLD,REP,CMP)),CMPVAL'="" S DATA(FLD,REP,CMP)=CMPVAL
|
---|
| 124 | . . I '$D(DATA(FLD,REP)),REPVAL'="",FLDVAL[RS S DATA(FLD,REP)=REPVAL
|
---|
| 125 | . I '$D(DATA(FLD)),FLDVAL'="" S DATA(FLD)=FLDVAL
|
---|
| 126 | Q
|
---|
| 127 | ;
|
---|
| 128 | BLDSEG(DATA,HL) ;generic segment builder
|
---|
| 129 | ;
|
---|
| 130 | ; Input:
|
---|
| 131 | ; DATA - field data array [SUB1:field, SUB2:repetition,
|
---|
| 132 | ; SUB3:component, SUB4:sub-component]
|
---|
| 133 | ; HL - HL7 environment array
|
---|
| 134 | ;
|
---|
| 135 | ; Output:
|
---|
| 136 | ; Function Value - Formatted HL7 segment on success, "" on failure
|
---|
| 137 | ;
|
---|
| 138 | N CMP ;component subscript
|
---|
| 139 | N CMPVAL ;component value
|
---|
| 140 | N FLD ;field subscript
|
---|
| 141 | N FLDVAL ;field value
|
---|
| 142 | N REP ;repetition subscript
|
---|
| 143 | N REPVAL ;repetition value
|
---|
| 144 | N SUB ;sub-component subscript
|
---|
| 145 | N SUBVAL ;sub-component value
|
---|
| 146 | N FS ;field separator
|
---|
| 147 | N CS ;component separator
|
---|
| 148 | N RS ;repetition separator
|
---|
| 149 | N ES ;escape character
|
---|
| 150 | N SS ;sub-component separator
|
---|
| 151 | N SEG,SEP
|
---|
| 152 | ;
|
---|
| 153 | S FS=HL("FS")
|
---|
| 154 | S CS=$E(HL("ECH"))
|
---|
| 155 | S RS=$E(HL("ECH"),2)
|
---|
| 156 | S ES=$E(HL("ECH"),3)
|
---|
| 157 | S SS=$E(HL("ECH"),4)
|
---|
| 158 | ;
|
---|
| 159 | S SEG=$G(DATA(0))
|
---|
| 160 | F FLD=1:1:$O(DATA(""),-1) D
|
---|
| 161 | . S FLDVAL=$G(DATA(FLD)),SEP=FS
|
---|
| 162 | . S SEG=SEG_SEP_FLDVAL
|
---|
| 163 | . F REP=1:1:$O(DATA(FLD,""),-1) D
|
---|
| 164 | . . S REPVAL=$G(DATA(FLD,REP))
|
---|
| 165 | . . S SEP=$S(REP=1:"",1:RS)
|
---|
| 166 | . . S SEG=SEG_SEP_REPVAL
|
---|
| 167 | . . F CMP=1:1:$O(DATA(FLD,REP,""),-1) D
|
---|
| 168 | . . . S CMPVAL=$G(DATA(FLD,REP,CMP))
|
---|
| 169 | . . . S SEP=$S(CMP=1:"",1:CS)
|
---|
| 170 | . . . S SEG=SEG_SEP_CMPVAL
|
---|
| 171 | . . . F SUB=1:1:$O(DATA(FLD,REP,CMP,""),-1) D
|
---|
| 172 | . . . . S SUBVAL=$G(DATA(FLD,REP,CMP,SUB))
|
---|
| 173 | . . . . S SEP=$S(SUB=1:"",1:SS)
|
---|
| 174 | . . . . S SEG=SEG_SEP_SUBVAL
|
---|
| 175 | Q SEG
|
---|
| 176 | ;
|
---|
| 177 | BLDWP(WP,SEG,MAXLEN,FORMAT,FMTLEN,HL) ;
|
---|
| 178 | ;Builds segment nodes to add word processing fields to a segment
|
---|
| 179 | N CNT,LINE,LAST,FS,RS,LENGTH,I
|
---|
| 180 | I MAXLEN<1 S MAXLEN=99999999999999999
|
---|
| 181 | S FS=HL("FS") ;field separator
|
---|
| 182 | S RS=$E(HL("ECH"),2) ;repeat separator
|
---|
| 183 | S CNT=$O(SEG(""),-1)+1
|
---|
| 184 | S SEG(CNT)=FS
|
---|
| 185 | S FMTLEN=0
|
---|
| 186 | S LENGTH=0
|
---|
| 187 | ;
|
---|
| 188 | S I=0
|
---|
| 189 | F S I=$O(WP(I)) Q:'I D Q:LENGTH'<MAXLEN
|
---|
| 190 | . I $D(WP(I,0)) S LINE=$G(WP(I,0)) ;conventional WP field
|
---|
| 191 | . E S LINE=$G(WP(I))
|
---|
| 192 | . S LENGTH=LENGTH+$L(LINE)
|
---|
| 193 | . I LENGTH'<MAXLEN S LINE=$E(LINE,1,$L(LINE)-(LENGTH-MAXLEN))
|
---|
| 194 | . S LINE=$$ESCAPE(LINE,.HL)
|
---|
| 195 | . S LAST=$E(LINE,$L(LINE))
|
---|
| 196 | . ;first line
|
---|
| 197 | . I SEG(CNT)=FS S SEG(CNT)=FS_LINE,FMTLEN=FMTLEN+$L(SEG(CNT)) Q
|
---|
| 198 | . S CNT=CNT+1
|
---|
| 199 | . S SEG(CNT)=RS_LINE,FMTLEN=FMTLEN+$L(SEG(CNT))
|
---|
| 200 | . Q:'FORMAT
|
---|
| 201 | . ;attempt to keep sentences together
|
---|
| 202 | . I $E(LINE)=" "!(LAST=" ") S SEG(CNT)=LINE,FMTLEN=FMTLEN+$L(LINE)
|
---|
| 203 | . Q
|
---|
| 204 | Q
|
---|
| 205 | ;
|
---|
| 206 | ESCAPE(VAL,HL) ;Escape any special characters
|
---|
| 207 | ; *** Does not handle long strings of special characters ***
|
---|
| 208 | ;
|
---|
| 209 | ; Input:
|
---|
| 210 | ; VAL - value to escape
|
---|
| 211 | ; HL - HL7 environment array
|
---|
| 212 | ;
|
---|
| 213 | ; Output:
|
---|
| 214 | ; VAL - passed by reference
|
---|
| 215 | ;
|
---|
| 216 | N FS ;field separator
|
---|
| 217 | N CS ;component separator
|
---|
| 218 | N RS ;repetition separator
|
---|
| 219 | N ES ;escape character
|
---|
| 220 | N SS ;sub-component separator
|
---|
| 221 | N L,STR,I
|
---|
| 222 | ;
|
---|
| 223 | S FS=HL("FS")
|
---|
| 224 | S CS=$E(HL("ECH"))
|
---|
| 225 | S RS=$E(HL("ECH"),2)
|
---|
| 226 | S ES=$E(HL("ECH"),3)
|
---|
| 227 | S SS=$E(HL("ECH"),4)
|
---|
| 228 | ;
|
---|
| 229 | I VAL[ES D
|
---|
| 230 | . S L=$L(VAL,ES),STR=""
|
---|
| 231 | . F I=1:1:L S $P(STR,ES_"E"_ES,I)=$P(VAL,ES,I)
|
---|
| 232 | . S VAL=STR
|
---|
| 233 | I VAL[FS D
|
---|
| 234 | . S L=$L(VAL,FS),STR=""
|
---|
| 235 | . F I=1:1:L S $P(STR,ES_"F"_ES,I)=$P(VAL,FS,I)
|
---|
| 236 | . S VAL=STR
|
---|
| 237 | I VAL[RS D
|
---|
| 238 | . S L=$L(VAL,RS),STR=""
|
---|
| 239 | . F I=1:1:L S $P(STR,ES_"R"_ES,I)=$P(VAL,RS,I)
|
---|
| 240 | . S VAL=STR
|
---|
| 241 | I VAL[CS D
|
---|
| 242 | . S L=$L(VAL,CS),STR=""
|
---|
| 243 | . F I=1:1:L S $P(STR,ES_"S"_ES,I)=$P(VAL,CS,I)
|
---|
| 244 | . S VAL=STR
|
---|
| 245 | I VAL[SS D
|
---|
| 246 | . S L=$L(VAL,SS),STR=""
|
---|
| 247 | . F I=1:1:L S $P(STR,ES_"T"_ES,I)=$P(VAL,SS,I)
|
---|
| 248 | . S VAL=STR
|
---|
| 249 | Q VAL
|
---|
| 250 | ;
|
---|
| 251 | UNESC(VAL,HL) ;Reconstitute any escaped characters
|
---|
| 252 | ;
|
---|
| 253 | ; Input:
|
---|
| 254 | ; VAL - Value to reconstitute
|
---|
| 255 | ; HL - HL7 environment array
|
---|
| 256 | ;
|
---|
| 257 | ; Output:
|
---|
| 258 | ; VAL - passed by reference
|
---|
| 259 | ;
|
---|
| 260 | N FS ;field separator
|
---|
| 261 | N CS ;component separator
|
---|
| 262 | N RS ;repetition separator
|
---|
| 263 | N ES ;escape character
|
---|
| 264 | N SS ;sub-component separator
|
---|
| 265 | N L,STR,I,FESC,CESC,RESC,EESC,SESC
|
---|
| 266 | ;
|
---|
| 267 | S FS=HL("FS")
|
---|
| 268 | S CS=$E(HL("ECH"))
|
---|
| 269 | S RS=$E(HL("ECH"),2)
|
---|
| 270 | S ES=$E(HL("ECH"),3)
|
---|
| 271 | S SS=$E(HL("ECH"),4)
|
---|
| 272 | S FESC=ES_"F"_ES
|
---|
| 273 | S CESC=ES_"S"_ES
|
---|
| 274 | S RESC=ES_"R"_ES
|
---|
| 275 | S EESC=ES_"E"_ES
|
---|
| 276 | S SESC=ES_"T"_ES
|
---|
| 277 | ;
|
---|
| 278 | I VAL'[ES Q VAL
|
---|
| 279 | I VAL[FESC D
|
---|
| 280 | . S L=$L(VAL,FESC),STR=""
|
---|
| 281 | . F I=1:1:L S $P(STR,FS,I)=$P(VAL,FESC,I)
|
---|
| 282 | . S VAL=STR
|
---|
| 283 | I VAL[CESC D
|
---|
| 284 | . S L=$L(VAL,CESC),STR=""
|
---|
| 285 | . F I=1:1:L S $P(STR,CS,I)=$P(VAL,CESC,I)
|
---|
| 286 | . S VAL=STR
|
---|
| 287 | I VAL[RESC D
|
---|
| 288 | . S L=$L(VAL,RESC),STR=""
|
---|
| 289 | . F I=1:1:L S $P(STR,RS,I)=$P(VAL,RESC,I)
|
---|
| 290 | . S VAL=STR
|
---|
| 291 | I VAL[SESC D
|
---|
| 292 | . S L=$L(VAL,SESC),STR=""
|
---|
| 293 | . F I=1:1:L S $P(STR,SS,I)=$P(VAL,SESC,I)
|
---|
| 294 | . S VAL=STR
|
---|
| 295 | I VAL[EESC D
|
---|
| 296 | . S L=$L(VAL,EESC),STR=""
|
---|
| 297 | . F I=1:1:L S $P(STR,ES,I)=$P(VAL,EESC,I)
|
---|
| 298 | . S VAL=STR
|
---|
| 299 | Q VAL
|
---|
| 300 | ;
|
---|