Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2023 09 gg misc fixes 4 #776

Merged
merged 7 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
* Loader: Fix up parsing of logical models
* Loader: Fix handling of CDA example fragments
* Loader: Fix bug parsing extension with no value in JSON for the validator
* Validator: Fix for issue parsing SHC and not recording line/col correctly
* Validator: Fix issue validating CDA FHIR Path constraints
* Validator: Better error handling validating codes in concept maps
* Validator: Validate special resource rules on contained resources and Bundle entries
* Validator: Improved error messages of observation bp
* Validator: Fix up WG internal model for changes to workgroups
* Validator: fix misleading error message inferring system when filters in play
* Validator: Fix type handling for logical models (CDA fixes)
* Version convertor: Fix version conversion issue between r4 and r5 charge definition issue
* Renderer: Fix rendering extension and missed profile on Reference()
* Renderer: fix wrong generation of logical models (for CDA)
* Renderer: Don't create wrong phinvads references
* Link Checker: Don't fail in link checking for illegal file references
* Publication Process: exit code = 1 unless publication run is succesful
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public FetchedResource setElement(Element element) {
return this;
}

public void setType(String type) {
this.type = type;
}

public String getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,27 +704,35 @@ private boolean checkResolveLink(String filename, Location loc, String path, Str
page = filename;
} else if (page.contains("#")) {
name = page.substring(page.indexOf("#")+1);
try {
if (altRootFolder != null && filename.startsWith(altRootFolder))
page = Utilities.path(altRootFolder, page.substring(0, page.indexOf("#")).replace("/", File.separator));
else
page = Utilities.path(rootFolder, page.substring(0, page.indexOf("#")).replace("/", File.separator));
} catch (Exception e) {
page = null;
}
} else {
String folder = Utilities.getDirectoryForFile(filename);
page = Utilities.path(folder == null ? (altRootFolder != null && filename.startsWith(altRootFolder) ? altRootFolder : rootFolder) : folder, page.replace("/", File.separator));
}
LoadedFile f = cache.get(page);
if (f != null) {
if (Utilities.noString(name))
resolved = true;
else {
resolved = f.targets.contains(name);
tgtList = " (valid targets: "+(f.targets.size() > 40 ? Integer.toString(f.targets.size())+" targets" : f.targets.toString())+")";
for (String s : f.targets) {
if (s.equalsIgnoreCase(name)) {
tgtList = (" - case is wrong ('"+s+"')");
if (page != null) {
LoadedFile f = cache.get(page);
if (f != null) {
if (Utilities.noString(name))
resolved = true;
else {
resolved = f.targets.contains(name);
tgtList = " (valid targets: "+(f.targets.size() > 40 ? Integer.toString(f.targets.size())+" targets" : f.targets.toString())+")";
for (String s : f.targets) {
if (s.equalsIgnoreCase(name)) {
tgtList = (" - case is wrong ('"+s+"')");
}
}
}
}
} else {
resolved = false;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ private String makeTemplateJekyllIndexPage() {
}

private String makeTemplateQAPage() {
String page = "<!DOCTYPE HTML><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>Template QA Page</title></head><body><p><b>Template {{npm}} QA</b></p><p>No useful QA on templates - if you see this page, the template buitl ok.</p></body></html>";
String page = "<!DOCTYPE HTML><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>Template QA Page</title></head><body><p><b>Template {{npm}} QA</b></p><p>No useful QA on templates - if you see this page, the template built ok.</p></body></html>";
return page.replace("{{npm}}", templateInfo.asString("name"));
}

Expand Down Expand Up @@ -6029,34 +6029,46 @@ private void loadAsElementModel(FetchedFile file, FetchedResource r, Implementat

if (e != null) {
try {
if (!Utilities.noString(e.getIdBase())) {
checkResourceUnique(e.fhirType()+"/"+e.getIdBase());
}
String id;
boolean altered = false;

String id = e.getChildValue("id");
if (Utilities.noString(id)) {
if (e.hasChild("url")) {
String url = e.getChildValue("url");
String prefix = Utilities.pathURL(igpkp.getCanonical(), e.fhirType())+"/";
if (url.startsWith(prefix)) {
id = e.getChildValue("url").substring(prefix.length());
e.setChildValue("id", id);
altered = true;
}
prefix = Utilities.pathURL(altCanonical, e.fhirType())+"/";
if (url.startsWith(prefix)) {
id = e.getChildValue("url").substring(prefix.length());
e.setChildValue("id", id);
altered = true;
}
if (Utilities.noString(id)) {
throw new Exception("Resource has no id in "+file.getPath()+" and canonical URL ("+url+") does not start with the IG canonical URL ("+prefix+")");
boolean binary = false;
if (!context.getResourceNamesAsSet().contains(e.fhirType())) {
File f = new File(file.getPath());
id = f.getName();
id = id.substring(0, id.indexOf("."));
checkResourceUnique("Binary/"+id);
r.setElement(e).setId(id).setType("Binary");
igpkp.findConfiguration(file, r);
binary = true;
} else {
id = e.getChildValue("id");
if (!Utilities.noString(e.getIdBase())) {
checkResourceUnique(e.fhirType()+"/"+e.getIdBase());
}

if (Utilities.noString(id)) {
if (e.hasChild("url")) {
String url = e.getChildValue("url");
String prefix = Utilities.pathURL(igpkp.getCanonical(), e.fhirType())+"/";
if (url.startsWith(prefix)) {
id = e.getChildValue("url").substring(prefix.length());
e.setChildValue("id", id);
altered = true;
}
prefix = Utilities.pathURL(altCanonical, e.fhirType())+"/";
if (url.startsWith(prefix)) {
id = e.getChildValue("url").substring(prefix.length());
e.setChildValue("id", id);
altered = true;
}
if (Utilities.noString(id)) {
throw new Exception("Resource has no id in "+file.getPath()+" and canonical URL ("+url+") does not start with the IG canonical URL ("+prefix+")");
}
}
}
r.setElement(e).setId(id);
igpkp.findConfiguration(file, r);
}
r.setElement(e).setId(id);
igpkp.findConfiguration(file, r);
if (!suppressLoading) {
if (srcForLoad == null)
srcForLoad = findIGReference(r.fhirType(), r.getId());
Expand Down Expand Up @@ -6116,8 +6128,9 @@ else if (file.getContentType().contains("xml"))
if (new AdjunctFileLoader(binaryPaths, cql).replaceAttachments1(file, r, metadataResourceNames())) {
altered = true;
}
if ((altered && r.getResource() != null) || (ver.equals(Constants.VERSION) && r.getResource() == null))
if (!binary && ((altered && r.getResource() != null) || (ver.equals(Constants.VERSION) && r.getResource() == null && context.getResourceNamesAsSet().contains(r.fhirType())))) {
r.setResource(new ObjectConverter(context).convert(r.getElement()));
}
if ((altered && r.getResource() == null)) {
if (file.getContentType().contains("json")) {
saveToJson(file, e);
Expand Down Expand Up @@ -6696,7 +6709,6 @@ private void generateSnapshot(FetchedFile f, FetchedResource r, StructureDefinit
}

if (changed || (!r.getElement().hasChild("snapshot") && sd.hasSnapshot())) {
// for big snapshots, this can take considerable time, and there's really no reason to do it
r.setElement(convertToElement(r, sd));
}
r.getElement().setUserData("profileutils.snapshot.errors", messages);
Expand Down Expand Up @@ -6925,28 +6937,32 @@ private void validate() throws Exception {
try {
logDebugMessage(LogCategory.PROGRESS, " .. validate "+f.getName());
logDebugMessage(LogCategory.PROGRESS, " .. "+f.getName());
for (FetchedResource r : f.getResources()) {
if (!r.isValidated()) {
logDebugMessage(LogCategory.PROGRESS, " validating "+r.getTitle());
validate(f, r);
}
}
FetchedResource r = f.getResources().get(0);
if (f.getLogical() != null && f.getResources().size() == 1 && r.fhirType().equals("Binary")) {
Binary bin = (Binary) r.getResource();
StructureDefinition profile = context.fetchResource(StructureDefinition.class, f.getLogical());
List<ValidationMessage> errs = new ArrayList<ValidationMessage>();
if (profile == null) {
errs.add(new ValidationMessage(Source.InstanceValidator, IssueType.NOTFOUND, "file", context.formatMessage(I18nConstants.Bundle_BUNDLE_Entry_NO_LOGICAL_EXPL, r.getId(), f.getLogical()), IssueSeverity.ERROR));
} else {
FhirFormat fmt = FhirFormat.readFromMimeType(bin.getContentType());
Session tts = tt.start("validation");
List<StructureDefinition> profiles = new ArrayList<>();
profiles.add(profile);
validate(f, r, bin, errs, fmt, profiles);
tts.end();
FetchedResource r0 = f.getResources().get(0);
if (f.getLogical() != null && f.getResources().size() == 1 && !r0.fhirType().equals("Binary")) {
throw new Error("Not done yet");
} else {
for (FetchedResource r : f.getResources()) {
if (!r.isValidated()) {
logDebugMessage(LogCategory.PROGRESS, " validating "+r.getTitle());
validate(f, r);
}
}
if (f.getLogical() != null && f.getResources().size() == 1 && r0.fhirType().equals("Binary")) {
Binary bin = (Binary) r0.getResource();
StructureDefinition profile = context.fetchResource(StructureDefinition.class, f.getLogical());
List<ValidationMessage> errs = new ArrayList<ValidationMessage>();
if (profile == null) {
errs.add(new ValidationMessage(Source.InstanceValidator, IssueType.NOTFOUND, "file", context.formatMessage(I18nConstants.Bundle_BUNDLE_Entry_NO_LOGICAL_EXPL, r0.getId(), f.getLogical()), IssueSeverity.ERROR));
} else {
FhirFormat fmt = FhirFormat.readFromMimeType(bin.getContentType());
Session tts = tt.start("validation");
List<StructureDefinition> profiles = new ArrayList<>();
profiles.add(profile);
validate(f, r0, bin, errs, fmt, profiles);
tts.end();
}
processValidationOutcomes(f, r0, errs);
}
processValidationOutcomes(f, r, errs);
}
} finally {
f.finish("validate");
Expand Down Expand Up @@ -6990,6 +7006,17 @@ private void validate(FetchedFile f, FetchedResource r, List<ValidationMessage>
}
}

private void validate(FetchedFile f, FetchedResource r, List<ValidationMessage> errs, Binary bin, StructureDefinition sd) {
long ts = System.currentTimeMillis();
List<StructureDefinition> profiles = new ArrayList<StructureDefinition>();
profiles.add(sd);
validator.validate(r.getElement(), errs, new ByteArrayInputStream(bin.getContent()), FhirFormat.readFromMimeType(bin.getContentType()), profiles);
long tf = System.currentTimeMillis();
if (tf-ts > validationLogTime && validationLogTime > 0) {
reportLongValidation(f, r, tf-ts);
}
}

private void validate(FetchedFile f, FetchedResource r, List<ValidationMessage> errs, Resource ber) {
long ts = System.currentTimeMillis();
validator.validate(r.getElement(), errs, ber, ber.getUserString("profile"));
Expand Down Expand Up @@ -7218,6 +7245,10 @@ private void validate(FetchedFile file, FetchedResource r) throws Exception {
} else if (res.hasUserData("profile")) {
validate(file, r, errs, res);
}
} else if (r.getResource() != null && r.getResource() instanceof Binary && file.getLogical() != null && context.hasResource(StructureDefinition.class, file.getLogical())) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, file.getLogical());
Binary bin = (Binary) r.getResource();
validate(file, r, errs, bin, sd);
} else if (r.getResource() != null && r.getResource() instanceof Binary && r.getExampleUri() != null) {
Binary bin = (Binary) r.getResource();
validate(file, r, errs, bin);
Expand Down Expand Up @@ -7747,7 +7778,8 @@ private Element convertToElement(FetchedResource r, Resource res) throws Excepti
org.hl7.fhir.r5.formats.JsonParser jp = new org.hl7.fhir.r5.formats.JsonParser();
jp.compose(bs, res);
}
ByteArrayInputStream bi = new ByteArrayInputStream(bs.toByteArray());
byte[] cnt = bs.toByteArray();
ByteArrayInputStream bi = new ByteArrayInputStream(cnt);
Element e = new org.hl7.fhir.r5.elementmodel.JsonParser(context).parseSingle(bi, null);
if (xhtml != null) {
Element div = e.getNamedChild("text").getNamedChild("div");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,23 @@ public String getPath(String url, String def, String rt, String id) throws FHIRE
if (special != null) {
switch (special) {
case Simplifier: return "https://simplifier.net/resolve?scope="+pi.name()+"@"+pi.version()+"&canonical="+url;
case PhinVads: if (url.startsWith(base))
return "??phinvads??";
else
break;
case PhinVads:
try {
if (url.startsWith(base)) {
final String fileName = Utilities.urlTail(url) + "json";

if ((isValidFilename(fileName) && pi.hasFile("package", fileName))
|| pi.hasCanonical(url)) {
return "phinvads_broken_link.html";
} else {
return null;
}

} else
break;
} catch (IOException e) {
return null;
}
case Vsac: if (url.contains("cts.nlm.nih.gov")) {
return url.replace("http://cts.nlm.nih.gov/fhir/ValueSet/", "https://vsac.nlm.nih.gov/valueset/")+"/expansion";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ public String snapshot(String defnFile, Set<String> outputTracker, boolean toTab
return "";
else {
sdr.getContext().setStructureMode(mode);
return new XhtmlComposer(XhtmlComposer.HTML).compose(sdr.generateTable(defnFile, sd, false, destDir, false, sd.getId(), true, corePath, "", false, false, outputTracker, false, gen, toTabs ? ANCHOR_PREFIX_SNAP : ANCHOR_PREFIX_SNAP));
return new XhtmlComposer(XhtmlComposer.HTML).compose(sdr.generateTable(defnFile, sd, false, destDir, false, sd.getId(), true, corePath, "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, outputTracker, false, gen, toTabs ? ANCHOR_PREFIX_SNAP : ANCHOR_PREFIX_SNAP));
}
}

Expand All @@ -466,7 +466,7 @@ public String byKey(String defnFile, Set<String> outputTracker, boolean toTabs,

sdCopy.getSnapshot().setElement(getKeyElements());
sdr.getContext().setStructureMode(mode);
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", false, false, outputTracker, true, gen, toTabs ? ANCHOR_PREFIX_KEY : ANCHOR_PREFIX_SNAP);
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, outputTracker, true, gen, toTabs ? ANCHOR_PREFIX_KEY : ANCHOR_PREFIX_SNAP);

return composer.compose(table);
}
Expand All @@ -481,7 +481,7 @@ public String byMustSupport(String defnFile, Set<String> outputTracker, boolean
sdr.getContext().setStructureMode(mode);

sdCopy.getSnapshot().setElement(getMustSupportElements());
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", false, false, outputTracker, true, gen, toTabs ? ANCHOR_PREFIX_MS : ANCHOR_PREFIX_SNAP);
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, outputTracker, true, gen, toTabs ? ANCHOR_PREFIX_MS : ANCHOR_PREFIX_SNAP);

return composer.compose(table);
}
Expand Down Expand Up @@ -524,7 +524,7 @@ public String byKeyElements(String defnFile, Set<String> outputTracker) throws I
List<ElementDefinition> keyElements = getKeyElements();

sdCopy.getSnapshot().setElement(keyElements);
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", false, false, outputTracker, true, gen, ANCHOR_PREFIX_KEY);
org.hl7.fhir.utilities.xhtml.XhtmlNode table = sdr.generateTable(defnFile, sdCopy, false, destDir, false, sdCopy.getId(), true, corePath, "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, outputTracker, true, gen, ANCHOR_PREFIX_KEY);

return composer.compose(table);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

public class PublicationProcess {

private int exitCode = 1;

/*
* checks that must be run prior to runing this:
*
Expand Down Expand Up @@ -131,6 +133,7 @@ public void publish(String source, String web, String date, String registrySourc
e.printStackTrace();
}
System.out.println("Full log in "+logger.getFilename());
System.exit(exitCode);
}

private static String removePassword(String[] args, int i) {
Expand Down Expand Up @@ -578,6 +581,7 @@ private void doPublish(File fSource, File fOutput, JsonObject qa, String destina
System.out.println("No!");
System.out.print("Changes not applied. Finished");
}
exitCode = 0;
}

private List<String> loadSubPackageList(String path) throws JsonException, IOException {
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<version>1.4.9-SNAPSHOT</version> <!-- See the note above -->

<properties>
<core_version>6.1.8</core_version>
<core_version>6.1.9-SNAPSHOT</core_version>
<maven_surefire_version>3.0.0-M5</maven_surefire_version>
<apache_poi_version>5.2.1</apache_poi_version>
<okhttp.version>4.11.0</okhttp.version>
Expand Down
Loading