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 | ;
|
---|