ABS383A ; Read the Data Dictionary and produce an M tree
describing a FileMan file [ 12/05/1999
5:01 PM ]
; For CECS 383: The Science and Technology of the World
Wide Web by Arthur B. Smith (754104)
MkTree(FileNum) ; Construct the tree for the file with file number FileNum
in ^ABS383(FileNum)
; This result global will have a physical structure
corresponding to the logical structure of the
; data file, i.e., each depth of subfile is a separate
subscript level in the result global.
;
; The first subscript of the result global is the file
number. Each subsequent subscript is a
; field number (hierarchically so that nested subfiles
add additional field number subscripts).
;
; The data stored in each node is:
FILE,FIELD^LABEL^TYPE^REQUIRED[^INDEX]
; where FILE,FIELD is the file and field numbers
(uniquely identifies this entry)
; and LABEL is the field label
; and TYPE is the field type ("Short
Text"|"Numeric"|POINTER|"Date"|"Set of
Codes"|
;
"Computed"|"M Code"|"Variable
Pointer"|"Unknown Type"|
;
"FILE"|"Multi-line Text")
; where
POINTER is "Pointer to " FileNum " (" FileName
")"
; and REQUIRED is the optionality
("Required"|"Optional") of the field
; and INDEX is a comma separated list of cross references
on this field.
;
; The result global also contains a cross reference in
^ABS383("FNUM",FILE) (where
; FILE is the file number) which contains the root of the
(sub)file in the result global.
;
; The result global also contains a cross reference in
^ABS383("XREF",SFF,FILE,XREF)
; where SFF is the (Sub)File Number, comma, Field Number
of the cross-referenced field
; and FILE is the File Number where the cross reference
is found (may be any ancestor of SFF)
; and XREF is the name (subscript) of the cross
reference.
Set
U="^"
Quit:'$$VFILE^DILFD(FileNum) ; Make sure the file exists!
Set
^ABS383(FileNum)=FileNum_U_$Order(^DD(FileNum,0,"NM",""))_U_"FILE"
; Recursively process this file and all subfiles
Do
SubTree(FileNum,"^ABS383("_FileNum_")")
Quit
SubTree(FNum,Root) ; Process all the fields in (sub)file FNum, adding them to the tree
at Root
; NOTE: Root
should already exist from a previous call or before the first call
; NOTE: This
processes subfiles by recursive calls
New Sub,Flags
Set ^ABS383("FNUM",FNum)=Root ; Add the cross reference so we can find
subfiles!
Set Sub=0
For Set
Sub=$Order(^DD(FNum,Sub)) Quit:Sub="" Quit:Sub]]"@" Do
. Set @Root@(Sub)=FNum_"z"_Sub_U_$Piece($Get(^DD(FNum,Sub,0)),U,1)
. Set Flags=$Piece($Get(^DD(FNum,Sub,0)),U,2)
. If $Piece($Piece($Get(^DD(FNum,Sub,0)),U,4),";",2)="0" Do
. . ; This is a
subfile or a word-processing field -- can't tell yet!
. . New SubFile
. . Set SubFile=+Flags ; This is the subfile
number
. . If $Piece($Get(^DD(SubFile,.01,0)),U,2)["W" Do ; This is a word-processing field!
. . . Set $Piece(@Root@(Sub),U,3)="Multi-line
Text"
. . Else Do ; This is a subfile!
. . . Set $Piece(@Root@(Sub),U,3)="FILE"
. . . Do SubTree(SubFile,$Name(@Root@(Sub))) ; RECURSIVE CALL!
. Else Do ; This is an ordinary
(non-multiple) field
. . Set $Piece(@Root@(Sub),U,3)=$Select(Flags["F":"Short
Text",Flags["N":"Numeric",Flags["P":"Pointer",Flags["D":"Date",Flags["S":"Set of
Codes",Flags["C":"Computed",Flags["K":"M
Code",Flags["V":"Variable
Pointer",1:"Unknown
Type")
. . If Flags?.E1"P"1.N0.1(1"."1.N).E Do ; This is a pointer -- find out to what!
. . . New Dest
. . . Set Dest=+$Extract(Flags,$Find(Flags,"P"),$Length(Flags))
. . . Set $Piece(@Root@(Sub),U,3)="Pointer
to "_Dest
. . . If $Data(^DD(Dest,0,"NM"))=10 Do
. . . . Set $Piece(@Root@(Sub),U,3)="Pointer
to "_Dest_" ("_$Order(^DD(Dest,0,"NM",""))_")"
. . . ; This
should (optionally?) DO MkTree^ABS383A(Dest) here... (or should that be
Dest\1?)
. Set $Piece(@Root@(Sub),U,4)=$Select(Flags["R":"Required",1:"Optional")
; Now catalog all
the cross references
New XRName,XFile,XField,XRoot
Set XRName=""
For Set
XRName=$Order(^DD(FNum,0,"IX",XRName)) Quit:XRName="" Do
. Set XFile=""
. For Set
XFile=$Order(^DD(FNum,0,"IX",XRName,XFile)) Quit:XFile="" Do
. . Set XField=""
. . For Set
XField=$Order(^DD(FNum,0,"IX",XRName,XFile,XField)) Quit:XField="" Do
. . . Set ^ABS383("XREF",XFile_","_XField,FNum,XRName)=""
. . . Set XRoot=$Get(^ABS383("FNUM",XFile))
. . . If $Length(XRoot) Do
. . . . Set Existing=$Piece(@XRoot@(XField),U,5)
. . . . If $Length(Existing) Set Existing=Existing_","
. . . . Set $Piece(@XRoot@(XField),U,5)=Existing_XRName
Quit