mod RULES2JSON is
  inc MAUDE2JSON-AUX .
  inc PL-PRINT .
  inc ESET .

***(
A rule specification (RuleSpec) is an object with the following fields
{ "stype" : "rule",
  "name" : String,  
  "shortname" : String,
  "consumed" : Participants,
  "produced" : Participants,
  "controls" : Participants,
  "description" : String,
  "metadata" : Object,
  "evidence" : EvidenceSpec
  }

Participants = JArray[String] | JArray[OccSpec]
  where the strings are expected to be names of occurrences in the
  context of a KB

)

**** 13aug24 clt add metadata capture
op ruleTemplate : -> String .
eq ruleTemplate = 
"\n %name:{\"stype\" : \"rule\",\n\
\t \"name\" : %name,\n\
\t \"shortname\" : %shortname,\n\
\t \"consumed\" : %consumed,\n\
\t \"produced\" : %produced,\n\
\t \"controls\" : %control,\n\
\t \"description\" : %description,\n\
\t \"metadata\" : %metadata,\n\
\t \"evidence\" : %evidence\n}" .


  vars kbname modname qid qid' : Qid .
  var ql toks : QidList .
  vars str str1 name basename evidence mdstr badstr badstr1 : String .
  var bindings : TBinds .
  vars es es' : ESet .
  vars  pnt pntlT ridT occT occsT ioccsT ooccsT boccsT : Term .
  vars tl pntl pntTL occTL : TermList .
  var enotes : Notes .
  var fres  next : FindResult .

  var alist sexpl : SexpL .
  var sexp? : Sexp? .
  var rules : RuleSet .
***  var mod : Module .

  op rules2json :  ESet Qid  -> String .
  op rules2json1 : RuleSet Notes TermList String String -> String .
  op rule2json : Notes Term String -> String .


  ceq rules2json(es,kbname) = str 
  if tm(modname,pntlT) := getVal(es,'tval,'tkb kbname, tm('BOOL,'true.Bool))
	/\ pntTL := pntlT2pntTL(if modname == 'BOOL
	                        then 'nil.PNTransList
	                        else pntlT fi) 
  /\ enotes := getNotes(es,'qval,kbname)
  /\ str :=  rules2json1(getRls(upModule(modname,true)),enotes,pntTL,"","") 
****  /\ es' := addEntry(es,'sval,'rules2json, sv(str)) 
.

  ceq rules2json1(rules,enotes,empty,str,badstr) = 
          fillTemplate(jobjTemplate, ("%jelts" :~ str1))
    if str1 := str 
         	 + (if ((str == "") or (badstr == "")) then "" else ",\n" fi) 
 					 + badstr .
 ceq rules2json1(rules,enotes,(pnt,pntl),str,badstr) = 
        rules2json1(rules,enotes,pntl,
             str + sep?(str,",\n") + fillTemplate(ruleTemplate,bindings),
             badstr1)
    if 'pnTrans[ridT,ioccsT,ooccsT,boccsT] := pnt
    /\ name := printRidTAll(ridT)
    /\ fres := rfind(name, PNRidSuffix, length(name)) 
    /\ basename := (if fres :: Nat then substr(name,0,fres) else name fi)  
    /\ ql(toks) := lookupd(enotes,basename, ql(nil))
    /\ evidence := mkEvidenceExp(toks)
    /\ mdstr := getMetaData(getAttrs(getRule(rules, qid(basename)) ))
    /\ ixs(next,sexp?) := readSexp(mdstr,0,length(mdstr)) 
    /\ alist := (if sexp? :: Sexp then sexp2l(sexp?) else nil fi) 
    /\ badstr1 := 
       (if (sexp? :: Sexp or mdstr == "")
        then badstr 
        else badstr + sep?(badstr,",\n")
             + fillTemplate(badTemplate,
                            (("%name" :~ squote("!!!" + basename)), 
                             ("%badstr" :~ squote(mdstr)) )) 
        fi) 
    /\ bindings := (("%name" :~ squote(name)),
                     ("%shortname" :~ squote(printRidT(ridT))),
                     ("%consumed" :~ occsT2flatSpec(ioccsT)),
                     ("%produced" :~ occsT2flatSpec(ooccsT)),
                     ("%control" :~ occsT2flatSpec(boccsT)),
                     ("%description" :~ squote("")),
                     ("%metadata" :~ alist2json(alist,nil,"")), 
                     ("%evidence" :~ evidence) )  .        

  eq rules2json1(rules,enotes,pntl,str,badstr) = "" [owise] .

  op occsT2flatSpec : Term -> String .
  eq occsT2flatSpec(occsT) = occTL2flatSpec(occsT2occTL(occsT) ,"") .

  op occTL2flatSpec : TermList String -> String .
  eq occTL2flatSpec(empty,str) = fillTemplate(jarrTemplate,("%jvals" :~ str)) .
  eq occTL2flatSpec((occT,tl),str) = occTL2flatSpec(tl,occT2flatSpec(occT,str)) .

  op occT2flatSpec : Term String -> String .
  eq occT2flatSpec(occT,str) = str + sep?(str,", ") + squote(occT2chatty(occT)) .

***(
An EvidenceSpec describes where evidence can be found.
{ "stype" : "evspec",
  "evtype" : {"datum","pubmed","other"},  
  "val": (String | JArray[String]),   
}
Currently supported evtypes are
evtype,  val
 datum,  String // filepath relative to KB evidence folder
 pubmed, JArray[String] // each string is a pubmed id
 other,  String  // self contained evidence description

Currently there is an evidence file that maps rule labels to
evidence.   Would be good to migrate this to rule metadata.
)

  op evidenceTemplate : -> String .
  eq evidenceTemplate =
"{\"stype\" : \"evspec\",\
 \"evtype\" : %evtype,\
 \"val\" : %val }" .



*** singleton beginning with "/" is datum file, ow  list of pmids
  op mkEvidenceExp : QidList -> String .
  eq mkEvidenceExp(nil) = squote("") .
  eq mkEvidenceExp(qid) = 
     (if (substr(string(qid),0,1) == "/" )
      then mkDatumEvidence(qid)
      else mkPMIDEvidence(qid,"") 
      fi) .

  eq mkEvidenceExp(qid qid' ql) = mkPMIDEvidence(qid qid' ql,"") .

  op mkDatumEvidence : Qid -> String .
  ceq mkDatumEvidence(qid) = fillTemplate(evidenceTemplate,bindings)
    if bindings := (("%evtype" :~ squote("datum")), ("%val" :~ squote(string(qid)))) .

  op mkPMIDEvidence : QidList String -> String .
  ceq mkPMIDEvidence(nil,str) = fillTemplate(evidenceTemplate,bindings)
    if bindings := (("%evtype" :~ squote("pubmed")), 
                    ("%val" :~ fillTemplate(jarrTemplate, ("%jvals" :~ str)))) .
  eq mkPMIDEvidence(qid ql,str) = 
         mkPMIDEvidence(ql,str + sep?(str,", ") + squote(string(qid)))  .

endm