MHV7U ;WAS/GPM - HL7 UTILITIES ; [4/19/06 12:41pm] ;;1.0;My HealtheVet;**1**;Aug 23, 2005 ;;Per VHA Directive 2004-038, this routine should not be modified. ; ;This routine contains generic utilities used when building ;or processing HL7 messages. ; Q ;Direct entry not supported ; LOADMSG(MSGROOT) ; Load HL7 message into temporary global for processing ; ;This subroutine assumes that all VistA HL7 environment variables are ;properly initialized and will produce a fatal error if they aren't. ; N CNT,SEG K @MSGROOT F SEG=1:1 X HLNEXT Q:HLQUIT'>0 D . S CNT=0 . S @MSGROOT@(SEG,CNT)=HLNODE . F S CNT=$O(HLNODE(CNT)) Q:'CNT S @MSGROOT@(SEG,CNT)=HLNODE(CNT) Q ; PARSEMSG(MSGROOT,HL) ; Message Parser ; Does not handle segments that span nodes ; Does not handle extremely long segments (uses a local) ; Does not handle long fields (segment parser doesn't) ; N SEG,CNT,DATA,MSG F CNT=1:1 Q:'$D(@MSGROOT@(CNT)) M SEG=@MSGROOT@(CNT) D . D PARSESEG(SEG(0),.DATA,.HL) . K @MSGROOT@(CNT) . I DATA(0)'="" M @MSGROOT@(CNT)=DATA . Q:'$D(SEG(1)) . ;Add handler for segments that span nodes here. . Q Q ; LOG(NAME,DATA,TYPE,NEW) ;Log to MHV application log ; ; Input: ; NAME - Name to identify log line ; DATA - Value,Tree, or Name of structure to put in log ; TYPE - Type of log entry ; S:Set Single Value ; M:Merge Tree ; I:Indirect Merge @ ; NEW - Flag to create new log entry ; ; Output: ; Updates log ; ; ^XTMP("MHV7LOG",0) - Head of log file ; ^XTMP("MHV7LOG",1) - if set indicates that logging is on ; ^XTMP("MHV7LOG",2) - contains the log ; ^XTMP("MHV7LOG",2,negated FM timestamp,$J,counter,NAME) - log entry ; ; ^TMP("MHV7LOG",$J) - Session current log entry (DTM) ; ;Quit if logging is not turned on Q:'$G(^XTMP("MHV7LOG",1)) N DTM,CNT ; Q:'$D(DATA) Q:$G(TYPE)="" Q:$G(NAME)="" S NAME=$TR(NAME,"^","-") ; ; Check ^TMP("MHV7LOG",$J) If no current log node start a new node I '$G(^TMP("MHV7LOG",$J)) S NEW=1 ; I $G(NEW) D . S DTM=-$$NOW^XLFDT() . K ^XTMP("MHV7LOG",2,DTM,$J) . S ^TMP("MHV7LOG",$J)=DTM . S CNT=1 . S ^XTMP("MHV7LOG",2,DTM,$J)=CNT . D AUTOPRG . Q E D . S DTM=^TMP("MHV7LOG",$J) . S CNT=$G(^XTMP("MHV7LOG",2,DTM,$J))+1 . S ^XTMP("MHV7LOG",2,DTM,$J)=CNT . Q ; I TYPE="S" S ^XTMP("MHV7LOG",2,DTM,$J,CNT,NAME)=DATA Q I TYPE="M" M ^XTMP("MHV7LOG",2,DTM,$J,CNT,NAME)=DATA Q I TYPE="I" M ^XTMP("MHV7LOG",2,DTM,$J,CNT,NAME)=@DATA Q ; Q ; AUTOPRG ; Q:'$G(^XTMP("MHV7LOG",1,"AUTOPURGE")) N DT,DAYS,RESULT ; Purge only once per day S DT=$$DT^XLFDT Q:$G(^XTMP("MHV7LOG",1,"AUTOPURGE","PURGE DATE"))=DT ; S DAYS=$G(^XTMP("MHV7LOG",1,"AUTOPURGE","DAYS")) I DAYS<1 S DAYS=7 ;*** Consider tasking the purge D LOGPRG^MHVUL1(.RESULT,$$HTFM^XLFDT($H-DAYS,1)) S ^XTMP("MHV7LOG",1,"AUTOPURGE","PURGE DATE")=DT Q ; TRIMSPC(STR) ;Trim leading and trailing spaces from a text string ; ; Input: ; STR - Text string ; ; Output: ; Function Value - Input text string with leading and trailing ; spaces removed ; N SPACE,POS,LEN S SPACE=$C(32) S LEN=$L(STR) S POS=1 F Q:$E(STR,POS)'=SPACE!(POS>LEN) S POS=POS+1 S STR=$E(STR,POS,LEN) S POS=$L(STR) F Q:$E(STR,POS)'=SPACE!(POS<1) S POS=POS-1 S STR=$E(STR,1,POS) Q STR ; PARSESEG(SEG,DATA,HL) ;Generic segment parser ;This procedure parses a single HL7 segment and builds an array ;subscripted by the field number containing the data for that field. ; Does not handle segments that span nodes ; ; Input: ; SEG - HL7 segment to parse ; HL - HL7 environment array ; ; Output: ; Function value - field data array [SUB1:field, SUB2:repetition, ; SUB3:component, SUB4:sub-component] ; N CMP ;component subscript N CMPVAL ;component value N FLD ;field subscript N FLDVAL ;field value N REP ;repetition subscript N REPVAL ;repetition value N SUB ;sub-component subscript N SUBVAL ;sub-component value N FS ;field separator N CS ;component separator N RS ;repetition separator N SS ;sub-component separator ; K DATA S FS=HL("FS") S CS=$E(HL("ECH")) S RS=$E(HL("ECH"),2) S SS=$E(HL("ECH"),4) ; S DATA(0)=$P(SEG,FS) S SEG=$P(SEG,FS,2,9999) F FLD=1:1:$L(SEG,FS) D . S FLDVAL=$P(SEG,FS,FLD) . F REP=1:1:$L(FLDVAL,RS) D . . S REPVAL=$P(FLDVAL,RS,REP) . . I REPVAL[CS F CMP=1:1:$L(REPVAL,CS) D . . . S CMPVAL=$P(REPVAL,CS,CMP) . . . I CMPVAL[SS F SUB=1:1:$L(CMPVAL,SS) D . . . . S SUBVAL=$P(CMPVAL,SS,SUB) . . . . I SUBVAL'="" S DATA(FLD,REP,CMP,SUB)=SUBVAL . . . I '$D(DATA(FLD,REP,CMP)),CMPVAL'="" S DATA(FLD,REP,CMP)=CMPVAL . . I '$D(DATA(FLD,REP)),REPVAL'="",FLDVAL[RS S DATA(FLD,REP)=REPVAL . I '$D(DATA(FLD)),FLDVAL'="" S DATA(FLD)=FLDVAL Q ; BLDSEG(DATA,HL) ;generic segment builder ; ; Input: ; DATA - field data array [SUB1:field, SUB2:repetition, ; SUB3:component, SUB4:sub-component] ; HL - HL7 environment array ; ; Output: ; Function Value - Formatted HL7 segment on success, "" on failure ; N CMP ;component subscript N CMPVAL ;component value N FLD ;field subscript N FLDVAL ;field value N REP ;repetition subscript N REPVAL ;repetition value N SUB ;sub-component subscript N SUBVAL ;sub-component value N FS ;field separator N CS ;component separator N RS ;repetition separator N ES ;escape character N SS ;sub-component separator N SEG,SEP ; S FS=HL("FS") S CS=$E(HL("ECH")) S RS=$E(HL("ECH"),2) S ES=$E(HL("ECH"),3) S SS=$E(HL("ECH"),4) ; S SEG=$G(DATA(0)) F FLD=1:1:$O(DATA(""),-1) D . S FLDVAL=$G(DATA(FLD)),SEP=FS . S SEG=SEG_SEP_FLDVAL . F REP=1:1:$O(DATA(FLD,""),-1) D . . S REPVAL=$G(DATA(FLD,REP)) . . S SEP=$S(REP=1:"",1:RS) . . S SEG=SEG_SEP_REPVAL . . F CMP=1:1:$O(DATA(FLD,REP,""),-1) D . . . S CMPVAL=$G(DATA(FLD,REP,CMP)) . . . S SEP=$S(CMP=1:"",1:CS) . . . S SEG=SEG_SEP_CMPVAL . . . F SUB=1:1:$O(DATA(FLD,REP,CMP,""),-1) D . . . . S SUBVAL=$G(DATA(FLD,REP,CMP,SUB)) . . . . S SEP=$S(SUB=1:"",1:SS) . . . . S SEG=SEG_SEP_SUBVAL Q SEG ; BLDWPSEG(WP,SEG,MAXLEN,HL) ; ;Builds segment nodes to add word processing fields to a segment N CNT,LINE,LAST,FS,RS,LENGTH I MAXLEN<1 S MAXLEN=999999999999 S FS=HL("FS") ;field separator S RS=$E(HL("ECH"),2) ;repeat separator S CNT=$O(SEG(""),-1)+1 S LINE=$O(WP(0)) S LENGTH=$L(LINE) S SEG(CNT)="" S SEG(CNT)=FS_$$ESCAPE($G(WP(LINE,0)),.HL) F S LINE=$O(WP(LINE)) Q:LINE="" D Q:LENGTH'