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