Home   Package List   Routine Alphabetical List   Global Alphabetical List   FileMan Files List   FileMan Sub-Files List   Package Component Lists   Package-Namespace Mapping  
Routine: YTWJSONE

YTWJSONE.m

Go to the documentation of this file.
  1. YTWJSONE ;SLC/KCM - Simple Editor for JSON Instrument Spec ; 7/20/2018
  1. ;;5.01;MENTAL HEALTH;**141,172**;Dec 30, 1994;Build 10
  1. ;
  1. ; Usage: D EN^YTWJSONE edit entry spec JSON & update checksum
  1. ; D VALIDATE^YTWJSONE checks recorded checksum against JSON actual
  1. ;
  1. EN ; edit instrument Entry Specification
  1. K ^TMP("YTQ-EDIT",$J)
  1. N SPEC,TESTNM,DONE,ERRS,CRCOLD,CRCNEW
  1. S SPEC=$$LOOKUP() Q:'SPEC
  1. S TESTNM=$P(^YTT(601.71,+^YTT(601.712,SPEC,0),0),U)
  1. S CRCOLD=$P(^YTT(601.712,SPEC,0),U,3)
  1. M ^TMP("YTQ-EDIT",$J)=^YTT(601.712,SPEC,1)
  1. S DONE=0 F D Q:DONE
  1. . K ERRS S DONE=1
  1. . D EDIT(TESTNM)
  1. . I '$$HASMODS(SPEC) W !,"Nothing changed" QUIT
  1. . D CHKSPEC($NA(^TMP("YTQ-EDIT",$J)),.ERRS,.CRCNEW)
  1. . I $G(ERRS) S DONE=$S($$EOP:0,1:1) QUIT
  1. . D SAVE712(SPEC,CRCNEW)
  1. . W !,"Changes saved. Old Checksum: ",CRCOLD," New Checksum: ",CRCNEW
  1. K ^TMP("YTQ-EDIT",$J)
  1. Q
  1. LOOKUP() ; return 601.712 IEN for selected instrument
  1. N DIC,X,Y
  1. S DIC="^YTT(601.712,",DIC(0)="AEMQ" D ^DIC
  1. Q +Y
  1. ;
  1. EDIT(TESTNM) ; edit copy of document in ^TMP("YTQ-EDIT",$J,
  1. N DIC,DDWAUTO,DDWFLAGS,DWLW,DWPK,DIWETXT,DIWESUB
  1. S DDWAUTO=1,DDWFLAGS="M"
  1. S DIC="^TMP(""YTQ-EDIT"","_$J_","
  1. S DWLW=132,DWPK=1,DIWETXT=TESTNM,DIWESUB="Entry Specification"
  1. D EN^DIWE
  1. Q
  1. HASMODS(SPEC) ; return 1 if edited version differs from 601.712
  1. N I,CHANGES,ORIG,EDIT
  1. S CHANGES=0
  1. S I=0 F S I=$O(^YTT(601.712,SPEC,1,I)) Q:'I D Q:CHANGES
  1. . S ORIG=$G(^YTT(601.712,SPEC,1,I,0))
  1. . S EDIT=$G(^TMP("YTQ-EDIT",$J,I,0))
  1. . I ORIG'=EDIT S CHANGES=1
  1. Q CHANGES
  1. ;
  1. OKSAVE() ; return 1 if OK to save changes
  1. N DIR,X,Y,DTOUT,DUOUT,DIRUT,DIROUT
  1. S DIR("A")="Save changes",DIR(0)="Y",DIR("B")="YES" D ^DIR
  1. Q +Y
  1. ;
  1. EOP() ; return 1 if continue, 0 if exit
  1. N DIR,X,Y,DTOUT,DUOUT,DIRUT,DIROUT
  1. S DIR(0)="E" D ^DIR
  1. Q +Y
  1. ;
  1. CHKSPEC(SRC,ERRS,CRC) ; parses JSON and calculates checksum
  1. ; .ERRS: returns 1 if JSON parses without errors
  1. ; .CRC: returns checksum
  1. K ^TMP("YTQ-JSON",$J),^TMP("YTQ-TREE",$J),^TMP("YTQ-LIST",$J)
  1. N JSON,TREE,LIST
  1. S JSON=$NA(^TMP("YTQ-JSON",$J))
  1. S TREE=$NA(^TMP("YTQ-TREE",$J))
  1. S LIST=$NA(^TMP("YTQ-LIST",$J))
  1. D FIXLF(SRC,JSON)
  1. D CHKJSON(JSON,TREE,.ERRS) I $G(ERRS) S CRC=0 QUIT
  1. D NAMEVAL(TREE,LIST)
  1. S CRC=$$NVCRC(LIST)
  1. K ^TMP("YTQ-JSON",$J),^TMP("YTQ-TREE",$J),^TMP("YTQ-LIST",$J)
  1. Q
  1. FIXLF(SRC,DEST) ; Load spec from SRC, cleaning up line feeds
  1. ; SPEC: reference to global with original JSON
  1. ; DEST: reference to global root for destination JSON
  1. N I,J,X,Y
  1. S (I,J)=0 F S I=$O(@SRC@(I)) Q:'I S X=^(I,0) D
  1. . S J=J+1,@DEST@(J)=X
  1. . I (($L(X)-$L($TR(X,"""","")))#2) D ; check for odd number of quotes
  1. . . F S I=I+1 Q:'$D(@SRC@(I,0)) D Q:Y[""""
  1. . . . S Y=@SRC@(I,0)
  1. . . . S @DEST@(J)=@DEST@(J)_Y
  1. Q
  1. CHKJSON(JSON,TREE,ERRS) ; decode JSON and display any errors
  1. ; JSON: reference to JSON global
  1. ; TREE: reference to TREE global
  1. ; .ERRORS: return errors found or 0
  1. N ERRORS
  1. D DECODE^XLFJSON(JSON,TREE,"ERRORS")
  1. I $G(ERRORS(0)) D
  1. . S ERRS=ERRORS(0)
  1. . W !,"ERRORS found while parsing JSON document"
  1. . N I S I=0 F S I=$O(ERRORS(I)) Q:'I W !,?2,ERRORS(I)
  1. . W !!,"Returning to editor..."
  1. Q
  1. ;
  1. NAMEVAL(TREE,LIST) ; Convert TREE to external object name/value list in LIST
  1. ; TREE: reference to global containing documents tree structure
  1. ; LIST: reference to global where @LIST@(name)=value will be saved
  1. ; NOTE -- resulting names will collate as string, so the order may be odd
  1. ; for example, obj[1], obj[10], obj[11], obj[2], etc.
  1. N ROOT,LROOT,SB,SL,S,X,I,NM,VAL,ADDQ
  1. S ROOT=$E(TREE,1,$L(TREE)-1),LROOT=$L(ROOT) ; drop last ")" for compare
  1. S X=TREE,SB=$QL(TREE)+1 ; begin at subscript after root
  1. F S X=$Q(@X) Q:$E(X,1,LROOT)'=ROOT D
  1. . S SL=$QL(X),NM="" ; SL is last subscript
  1. . I $D(@X@("\s"))!$D(@X@("\n")) Q ; node already evaluated
  1. . F I=SB:1:SL S S=$QS(X,I) S NM=NM_$S(+S:"["_S_"]",(I>3)&'S:"."_S,1:S)
  1. . S VAL=@X
  1. . S ADDQ=$$JSONSTR(VAL) ; check if num, str, bool
  1. . I $D(@X@("\s")) S ADDQ=1 ; "\s" forces string
  1. . I $D(@X@("\n")) S ADDQ=0 ; "\n" forces numeric
  1. . S @LIST@(NM)=$S(ADDQ:""""_VAL_"""",1:VAL) ; NM=VAL, NM collates as string
  1. Q
  1. JSONSTR(X) ; return 1 if should be treated as a string
  1. Q:X="true" 0 ; boolean
  1. Q:X="false" 0 ; boolean
  1. Q:X="null" 0 ; null object
  1. Q:+X=X 0 ; numeric
  1. Q 1
  1. ;
  1. NVCRC(LIST) ; return CRC32 for LIST(name)=value
  1. ; LIST: reference to global containing @LIST@(name)=value pairs
  1. N X,STR,CRC
  1. S CRC=0
  1. S X="" F S X=$O(@LIST@(X)) Q:'$L(X) D
  1. . S STR=X_"="_@LIST@(X)
  1. . S CRC=$$CRC32^XLFCRC(STR,CRC)
  1. Q CRC
  1. ;
  1. TSCRC() ; return CRC32 of all checksums for active instruments
  1. N IEN,X,CRC
  1. S (IEN,CRC)=0 F S IEN=$O(^YTT(601.712,IEN)) Q:'IEN D
  1. . S CRC=$$CRC32^XLFCRC($P(^YTT(601.712,IEN,0),U,3),CRC)
  1. Q CRC
  1. ;
  1. SHA1ALL() ; return SHA-1 of all checksums for active instruments
  1. N IEN,X
  1. S X=""
  1. S IEN=0 F S IEN=$O(^YTT(601.712,IEN)) Q:'IEN S X=X_$P(^(IEN,0),U,3)
  1. W !,"Length: ",$L(X)," X=",!,X
  1. W !,$$SHAHASH^XUSHSH(160,X,"H")
  1. Q
  1. SAVE712(IEN,CRC) ; save updated specification to 601.712
  1. ; expects ^TMP("YTQ-EDIT,$J,n,0) to be entry spec text
  1. N REC
  1. S REC(.02)=$$NOW^XLFDT
  1. S REC(.03)=CRC
  1. S REC(1)=$NA(^TMP("YTQ-EDIT",$J))
  1. D FMUPD^YTXCHGU(601.712,.REC,IEN)
  1. Q
  1. ;
  1. VALIDATE ; compare CRC with actual and check JSON structure
  1. N SPEC,TEST
  1. S SPEC=0 F S SPEC=$O(^YTT(601.712,SPEC)) Q:'SPEC D
  1. . S TEST=+$P(^YTT(601.712,SPEC,0),U)
  1. . I '$D(^YTT(601.71,TEST,0)) D QUIT
  1. . . W !,"Missing entry in 601.71: ",TEST," ",^YTT(601.712,SPEC,1,1,0)
  1. . W !,$P(^YTT(601.71,+^YTT(601.712,SPEC,0),0),U)
  1. . N ERRS,CRCCALC,CRCSAVED
  1. . S CRCSAVED=$P(^YTT(601.712,SPEC,0),U,3)
  1. . D CHKSPEC($NA(^YTT(601.712,SPEC,1)),.ERRS,.CRCCALC)
  1. . I '$G(ERRS),(CRCSAVED=CRCCALC) W ?30,"ok" QUIT
  1. . I CRCSAVED'=CRCCALC W ?30,"Saved Checksum: ",CRCSAVED," Actual: ",CRCCALC
  1. . I $G(ERRS) W " JSON errors"
  1. Q
  1. ;
  1. FILE(TEST,PATH) ; write JSON from 601.712 to host file in PATH
  1. N IEN,OK,NAME
  1. I TEST'=+TEST S TEST=$O(^YTT(601.71,"B",TEST,0)) Q:'TEST
  1. S IEN=$O(^YTT(601.712,"B",TEST,0)) Q:'IEN
  1. S NAME=$TR($P(^YTT(601.71,TEST,0),U)," ","_")_"-espec.json"
  1. ;
  1. K ^TMP($J)
  1. M ^TMP($J)=^YTT(601.712,IEN,1) ; so can use $$GTF^%ZISH
  1. K ^TMP($J,0) ; remove count & date node
  1. S OK=$$GTF^%ZISH($NA(^TMP($J,1,0)),2,PATH,NAME)
  1. I 'OK W !,"Error writing file: "_NAME
  1. K ^TMP($J)
  1. Q
  1. LOAD(TEST,PATH) ; read host file in PATH and load into 601.712
  1. N TESTNM,SPEC,FILE,OK,CRCOLD,CRCNEW,ERRS
  1. I TEST'=+TEST S TEST=$O(^YTT(601.71,"B",TEST,0)) QUIT:'TEST
  1. S TESTNM=$P(^YTT(601.71,TEST,0),U)
  1. S SPEC=$O(^YTT(601.712,"B",TEST,0)) QUIT:'SPEC
  1. S FILE=$TR(TESTNM," ","_")_"-espec.json"
  1. S CRCOLD=$P(^YTT(601.712,SPEC,0),U,3)
  1. ;
  1. K ^TMP("YTQ-EDIT",$J)
  1. S OK=$$FTG^%ZISH(PATH,FILE,$NA(^TMP("YTQ-EDIT",$J,1,0)),3)
  1. I 'OK W !,"Error reading file: "_FILE QUIT
  1. I '$$HASMODS(SPEC) W !,"Nothing changed" QUIT
  1. ;
  1. D CHKSPEC($NA(^TMP("YTQ-EDIT",$J)),.ERRS,.CRCNEW) QUIT:$G(ERRS)
  1. D SAVE712(SPEC,CRCNEW)
  1. W !,TESTNM," entry spec saved. Old Checksum: ",CRCOLD," New Checksum: ",CRCNEW
  1. K ^TMP("YTQ-EDIT",$J)
  1. Q