Skip to content

Commit

Permalink
Fix Vivian Generation failures due to DI*22.2*19
Browse files Browse the repository at this point in the history
The release notes for the patch
(https://foia-vista.worldvista.org/Patches_By_Application/DI-VA%20FILEMAN/DI-22p2_SEQ-15_PAT-19.txt)
say the following:

```
 1. Problem: INC11859284
     FM List File Attributes option doesn't display the Help-Prompt for a
     Word Processing field.  Also, the Description is from the top level,
     not the same level as the Help-Prompt.
    Resolution:
     Change DID1 & DID2 to display the Help-Prompt and Description from
     the sub data dictionary level.
```

I personally don't think that's the only thing that changed. There seems
to have been improved checking for subfiles, and some formatting
changes.

These DID* changes resulted in these two errors:

Error 1:
```
6: CMake Error at /opt/VistA-docs/Docs/CallerGraph/GraphGenerator.cmake:40 (message):
6:   Error running GraphGenerator:
6:
6:
6:
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/GraphGenerator.py", line 331, in <module>
6:       run(result)
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/GraphGenerator.py", line 305, in run
6:       printTemplateDeps=readIntoDictionary(args.printTemplateDep)
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/CrossReferenceBuilder.py", line 64, in buildCrossReferenceWithArgs
6:       printTemplateDeps=printTemplateDeps)
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/CrossReferenceBuilder.py", line 79, in buildCrossReference
6:       crossRef = parseDataDictionaryLogFile(crossRef, fileSchemaDir).getCrossReference()
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 614, in parseDataDictionaryLogFile
6:       DDFileParser.parseAllDataDictionaryListLog(fileSchemaDir, "*.schema")
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 576, in parseAllDataDictionaryListLog
6:       self.__parseDataDictionaryLogFile__(logFileName)
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 601, in __parseDataDictionaryLogFile__
6:       self._curParser.onSectionStart(line, self._curSect, self._curGlobal, self._crossRef)
6:     File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 168, in onSectionStart
6:       assert self._curFile, "Could not find subFile [%s] in file [%s] line [%s]" % (fileNo, Global.getFileNo(), line)
```

and Error 2:

```
  File "/opt/VistA/Utilities/Dox/PythonScripts/GraphGenerator.py", line 332, in <module>
    run(result)
  File "/opt/VistA/Utilities/Dox/PythonScripts/GraphGenerator.py", line 306, in run
    printTemplateDeps=readIntoDictionary(args.printTemplateDep)
  File "/opt/VistA/Utilities/Dox/PythonScripts/CrossReferenceBuilder.py", line 64, in buildCrossReferenceWithArgs
    printTemplateDeps=printTemplateDeps)
  File "/opt/VistA/Utilities/Dox/PythonScripts/CrossReferenceBuilder.py", line 79, in buildCrossReference
    crossRef = parseDataDictionaryLogFile(crossRef, fileSchemaDir).getCrossReference()
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 628, in parseDataDictionaryLogFile
    DDFileParser.parseAllDataDictionaryListLog(fileSchemaDir, "*.schema")
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 588, in parseAllDataDictionaryListLog
    self.__parseDataDictionaryLogFile__(logFileName)
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 615, in __parseDataDictionaryLogFile__
    self._curParser.onSectionStart(line, self._curSect, self._curGlobal, self._crossRef)
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 169, in onSectionStart
    self._isSubFile = float(fileNo) != float(Global.getFileNo())
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 407, in __createFieldByType__
    self.__createFieldByType__(fieldNo, fType, fName, fLocation, line, Global, CrossReference)
  File "/opt/VistA/Utilities/Dox/PythonScripts/DataDictionaryParser.py", line 408, in __createFieldByType__
    assert self._field, "Could not find the right type for %s, %s, %s, %s, %s" % (fType, fLocation, fieldNo, line, self._curFile.getFileNo())
AssertionError: Could not find the right type for 3VARIABLE POINTER, 0;1, 27, 162.03,27           ASSOCIATED 7078/583        0;13VARIABLE POINTER, 16
```

It took a while to investigate the cause of each error, and figure out a
way around it.

Error 1
-------
It was found that the FOIA instance contains a Corrupted DD for the
DOMAIN file. Notice the fact below that both fields 4.2 and 100 resolve
to the same subfile, 4.25; and FileMan now (it didn't previously) prints
out a DD for 4.25, when there is no Multiple declared in the file
(besides the Word Processing fields) saying that there is a Multiple in
subfile 4.25. The Vivian Generator crashed with an assert because of the
fact it's seeing a Subfile without an earlier declaration of a Multiple.
This is now solved by marking a field as Invalid and not proceeding
any further with emitting this field into the HTML.

```
4.2,4.2       NOTES                  5;0   WORD-PROCESSING #4.25   (NOWRAP)

              DESCRIPTION:
                                NETWORK NOTES should be used to document idiosyncracies which occur when communicating with the domain in question.

                LAST EDITED:      MAR 12, 1992
                DESCRIPTION:
                                  NETWORK NOTES should be used to document idiosyncracies which occur when communicating with the domain in question.

                CROSS-REFERENCE:  4.25^B
                                  1)= S ^DIC(4.2,DA(1),100,"B",$E(X,1,30),DA)=""
                                  2)= K ^DIC(4.2,DA(1),100,"B",$E(X,1,30),DA)

4.2,100       *MESSAGE STATISTICS MONTH 100;0   WORD-PROCESSING #4.25   (NOWRAP)

              DESCRIPTION:      Message statistics are collected by month.

                                SEE FIELD 7 ABOUT '*'

4.25,101.1      *MESSAGES SENT         0;2 NUMBER

                INPUT TRANSFORM:  K:+X'=X!(X>999999)!(X<0)!(X?.E1"."1N.N) X
                LAST EDITED:      OCT 26, 1989
                HELP-PROMPT:      Type a Number between 0 and 999999, 0 Decimal Digits
                DESCRIPTION:      This is the number of messages that were transmitted to other domains regardless of their origination site.  A prev
ients is also included.  Responses are
                                  included as if they were separate messages.

                                  SEE FIELD 7 ABOUT '*'

4.25,101.2      *MESSAGES RECEIVED     0;3 NUMBER

                INPUT TRANSFORM:  K:+X'=X!(X>999999)!(X<0)!(X?.E1"."1N.N) X
                LAST EDITED:      OCT 26, 1989
                HELP-PROMPT:      Type a Number between 0 and 999999, 0 Decimal Digits
                DESCRIPTION:      Messages and Responses rec'd are included in this count even if they are not received by a local recipient, but are

                                  SEE FIELD 7 ABOUT '*'.

4.25,101.3      *CHARACTERS SENT       0;4 NUMBER

                INPUT TRANSFORM:  K:+X'=X!(X>999999999)!(X<0)!(X?.E1"."1N.N) X
                LAST EDITED:      OCT 26, 1989
                HELP-PROMPT:      Type a Number between 0 and 999999999, 0 Decimal Digits
                DESCRIPTION:      This is a count of the number of characters that were in the text field of the messages sent in field 101.1.

                                  SEE FIELD 7 ABOUT '*'.

4.25,101.4      *CHARACTERS RECEIVED   0;5 NUMBER
...
```

Error 2
-------
File 162 has this in the DD:

```
162.03,27           ASSOCIATED 7078/583        0;13VARIABLE POINTER
```

Note that there is no space between the `0;13` and `VARIABLE POINTER`.
Vivian uses a regex that uses spaces to delimit the fields that it grabs
from the regex match. I looked around and found that you can designate a
field as a `FileManField.FIELD_TYPE_NONE` as a special value. So now the
field is still emitted, but it shows up a pointer with limited
information.
  • Loading branch information
shabiel committed Dec 29, 2021
1 parent d7c01e9 commit 5582925
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
Expand Up @@ -37,7 +37,7 @@ TORDateRangeDlg = class(TComponent)
property RelativeStart: string read FRelativeStart;
property RelativeStop: string read FRelativeStop;
published
property DateOnly: Boolean read FDateOnly write SetDateOnly; property FMDateStart: TFMDateTime read FFMDateStart write SetFMDateStart; property FMDateStop: TFMDateTime read FFMDateStop write SetFMDateStop; property Instruction: string read FInstruction write FInstruction; property LabelStart: string read FLabelStart write FLabelStart; property LabelStop: string read FLabelStop write FLabelStop; property RequireTime: Boolean read FRequireTime write SetRequireTime; property Format: string read FFormat write FFormat; property TextOfStart: string read FTextOfStart write SetTextOfStart; property TextOfStop: string read FTextOfStop write SetTextOfStop; end;
property DateOnly: Boolean read FDateOnly write SetDateOnly; property FMDateStart: TFMDateTime read FFMDateStart write SetFMDateStart; property FMDateStop: TFMDateTime read FFMDateStop write SetFMDateStop; property Instruction: string read FInstruction write FInstruction; property LabelStart: string read FLabelStart write FLabelStart; property LabelStop: string read FLabelStop write FLabelStop; property RequireTime: Boolean read FRequireTime write SetRequireTime; property Format: string read FFormat write FFormat; property TextOfStart: string read FTextOfStart write SetTextOfStart; property TextOfStop: string read FTextOfStop write SetTextOfStop; end;
procedure Register;

implementation
Expand Down Expand Up @@ -78,7 +78,7 @@ function TORDateRangeDlg.Execute: Boolean;
FCalStop.FMDateTime := FFMDateStop;
FCalStop.Text := FormatFMDateTime(FFormat, FFMDateStop);
end;
FCalStart.DateOnly := FDateOnly; FCalStop.DateOnly := FDateOnly; FCalStart.RequireTime := FRequireTime; FCalStop.RequireTime := FRequireTime; lblInstruct.Caption := FInstruction; lblStart.Caption := FLabelStart; lblStop.Caption := FLabelStop;
FCalStart.DateOnly := FDateOnly; FCalStop.DateOnly := FDateOnly; FCalStart.RequireTime := FRequireTime; FCalStop.RequireTime := FRequireTime; lblInstruct.Caption := FInstruction; lblStart.Caption := FLabelStart; lblStop.Caption := FLabelStop;
Result := (ShowModal = IDOK);
if Result then
begin
Expand Down
21 changes: 17 additions & 4 deletions Utilities/Dox/PythonScripts/DataDictionaryParser.py
Expand Up @@ -4,6 +4,7 @@
# the FileMan Schema and dependencies among packages.
#---------------------------------------------------------------------------
# Copyright 2012 The Open Source Electronic Health Record Agent
# Copyright 2021 Sam Habiel
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -155,6 +156,7 @@ def __init__(self):
self._curFile = None
self._field = None
self._isSubFile = False
self._isInvalid = False

def onSectionStart(self, line, section, Global, CrossReference):
self._lines = []
Expand All @@ -165,7 +167,10 @@ def onSectionStart(self, line, section, Global, CrossReference):
self._isSubFile = float(fileNo) != float(Global.getFileNo())
if self._isSubFile:
self._curFile = Global.getSubFileByFileNo(fileNo)
assert self._curFile, "Could not find subFile [%s] in file [%s] line [%s]" % (fileNo, Global.getFileNo(), line)
if not self._curFile:
logger.error("Invalid subfile [%s] in file [%s] in line [%s]" % (fileNo, Global.getFileNo(), line))
self._isInvalid = True
return
else:
self._curFile = Global
restOfLineStart = line.find("," + fieldNo) + len(fieldNo)
Expand Down Expand Up @@ -219,7 +224,10 @@ def onSectionStart(self, line, section, Global, CrossReference):
self.__parseFieldAttributes__(fType)

def onSectionEnd(self, line, section, Global, CrossReference):
if not self._lines:
if self._isInvalid:
self.__resetVar__()
pass
elif not self._lines:
pass
#elif self._isSubFilePointer and self._pointedToSubFile:
# self.__parsingSubFileDescription__()
Expand Down Expand Up @@ -394,7 +402,9 @@ def __createFieldByType__(self, fieldNo, fType, fName, fLocation, line, Global,
if fLocation:
fLocation = line[line.find(fLocation):self.MAXIMIUM_TYPE_START_INDEX]
self.__createFieldByType__(fieldNo, fType, fName, fLocation, line, Global, CrossReference)
assert self._field, "Could not find the right type for %s, %s, %s, %s, %s" % (fType, fLocation, fieldNo, line, self._curFile.getFileNo())
if not self._field:
logger.error("Could not find the right type for %s, %s, %s, %s, %s" % (fType, fLocation, fieldNo, line, self._curFile.getFileNo()))
self._field = FileManFieldFactory.createField(fieldNo, fName, FileManField.FIELD_TYPE_NONE, fLocation)

def __stripFieldAttributes__(self, fType):
outType = fType
Expand All @@ -416,6 +426,7 @@ def __resetVar__(self):
self._isSubFile = False
self._curFile = None
self._field = None
self._isInvalid = False

#===============================================================================
# A class to parse Pointed T By section in Data Dictionary schema log file output
Expand Down Expand Up @@ -572,7 +583,7 @@ def parseAllDataDictionaryListLog(self, dirName, pattern):
dataDictionaryLogFiles = os.path.join(dirName, pattern)
allFiles = glob.glob(dataDictionaryLogFiles)
for logFileName in allFiles:
logger.info("Start parsing log file [%s]" % logFileName)
logger.progress("Parsing log file [%s]" % logFileName)
self.__parseDataDictionaryLogFile__(logFileName)

def __parseDataDictionaryLogFile__(self, logFileName):
Expand All @@ -592,6 +603,8 @@ def __parseDataDictionaryLogFile__(self, logFileName):
if not line: # ignore the empty line
continue
section = self.__isSectionHeader__(line)
#if fileNo == "4.2" or fileNo == "162":
# logger.progress(line)
if section:
if self._curSect and self._curParser:
self._curParser.onSectionEnd(line, self._curSect, self._curGlobal, self._crossRef)
Expand Down

0 comments on commit 5582925

Please sign in to comment.