From 1e6990946641caaea71d1d172fe333735949e3ee Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 10 Nov 2021 17:04:51 +1100 Subject: [PATCH] Add warning about resources not linked to in bundles --- .../fhir/utilities/i18n/I18nConstants.java | 1 + .../src/main/resources/Messages.properties | 1 + .../instance/type/BundleValidator.java | 27 ++++++++++++++++--- .../instance/utils/EntrySummary.java | 16 ++++++++--- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index cdd79d2d5..d0c752264 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -32,6 +32,7 @@ public class I18nConstants { public static final String BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = "BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES"; public static final String BUNDLE_BUNDLE_ENTRY_NOTFOUND = "Bundle_BUNDLE_Entry_NotFound"; public static final String BUNDLE_BUNDLE_ENTRY_ORPHAN = "Bundle_BUNDLE_Entry_Orphan"; + public static final String BUNDLE_BUNDLE_ENTRY_REVERSE = "BUNDLE_BUNDLE_ENTRY_REVERSE"; public static final String BUNDLE_BUNDLE_ENTRY_TYPE = "Bundle_BUNDLE_Entry_Type"; public static final String BUNDLE_BUNDLE_ENTRY_TYPE2 = "Bundle_BUNDLE_Entry_Type2"; public static final String BUNDLE_BUNDLE_ENTRY_TYPE3 = "Bundle_BUNDLE_Entry_Type3"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index beddd6b7a..017cacba5 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -11,6 +11,7 @@ BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED = Except for transactions and batches, each Bundle_BUNDLE_Entry_NoProfile = No profile found for contained resource of type ''{0}'' Bundle_BUNDLE_Entry_NotFound = Can''t find ''{0}'' in the bundle ({1}) Bundle_BUNDLE_Entry_Orphan = Entry {0} isn''t reachable by traversing from first Bundle entry +BUNDLE_BUNDLE_ENTRY_REVERSE = Entry {0} isn''t reachable by traversing forwards from first Bundle entry, and isn''t a resource type that is typically used that way - check this is not missed somewhere Bundle_BUNDLE_Entry_Type = The type ''{0}'' is not valid - no resources allowed here (allowed = {1}) Bundle_BUNDLE_Entry_Type2 = The type ''{0}'' is not valid - must be {1} (allowed = {2}) Bundle_BUNDLE_Entry_Type3 = The type ''{0}'' is not valid - must be one of {1} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java index 55894563e..46067244e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java @@ -396,20 +396,30 @@ public class BundleValidator extends BaseValidator{ private void checkAllInterlinked(List errors, List entries, NodeStack stack, Element bundle, boolean isError) { List entryList = new ArrayList<>(); + int i = 0; for (Element entry : entries) { Element r = entry.getNamedChild(RESOURCE); if (r != null) { - entryList.add(new EntrySummary(entry, r)); + EntrySummary e = new EntrySummary(i, entry, r); + entryList.add(e); + System.out.println("Found entry "+e.dbg()); } + i++; } + for (EntrySummary e : entryList) { Set references = findReferences(e.getEntry()); for (String ref : references) { Element tgt = resolveInBundle(entries, ref, e.getEntry().getChildValue(FULL_URL), e.getResource().fhirType(), e.getResource().getIdBase()); if (tgt != null) { EntrySummary t = entryForTarget(entryList, tgt); - if (t != null) { - e.getTargets().add(t); + if (t != null ) { + if (t != e) { + System.out.println("Entry "+e.getIndex()+" refers to "+t.getIndex()+" by ref '"+ref+"'"); + e.getTargets().add(t); + } else { + System.out.println("Entry "+e.getIndex()+" refers to itself by '"+ref+"'"); + } } } } @@ -422,6 +432,7 @@ public class BundleValidator extends BaseValidator{ foundRevLinks = false; for (EntrySummary e : entryList) { if (!visited.contains(e)) { + System.out.println("Not visited "+e.getIndex()+" - check for reverse links"); boolean add = false; for (EntrySummary t : e.getTargets()) { if (visited.contains(t)) { @@ -429,6 +440,10 @@ public class BundleValidator extends BaseValidator{ } } if (add) { + warning(errors, IssueType.INFORMATIONAL, e.getEntry().line(), e.getEntry().col(), + stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), isExpectedToBeReverse(e.getResource().fhirType()), + I18nConstants.BUNDLE_BUNDLE_ENTRY_REVERSE, (e.getEntry().getChildValue(FULL_URL) != null ? "'" + e.getEntry().getChildValue(FULL_URL) + "'" : "")); + System.out.println("Found reverse links for "+e.getIndex()); foundRevLinks = true; visitLinked(visited, e); } @@ -436,7 +451,7 @@ public class BundleValidator extends BaseValidator{ } } while (foundRevLinks); - int i = 0; + i = 0; for (EntrySummary e : entryList) { Element entry = e.getEntry(); if (isError) { @@ -450,6 +465,10 @@ public class BundleValidator extends BaseValidator{ + private boolean isExpectedToBeReverse(String fhirType) { + return Utilities.existsInList(fhirType, "Provenance"); + } + private String uriRegexForVersion() { if (VersionUtilities.isR3Ver(context.getVersion())) return URI_REGEX3; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/EntrySummary.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/EntrySummary.java index 07b24f64a..8e1e33e17 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/EntrySummary.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/EntrySummary.java @@ -10,6 +10,7 @@ public class EntrySummary { Element entry; Element resource; List targets = new ArrayList<>(); + private int index; public Element getEntry() { return entry; @@ -38,8 +39,17 @@ public class EntrySummary { return this; } - public EntrySummary(Element entry, Element resource) { - this.entry = entry; - this.resource = resource; + public EntrySummary(int i, Element entry, Element resource) { + this.index = i; + this.entry = entry; + this.resource = resource; + } + + public String dbg() { + return ""+index+"="+ entry.getChildValue("fullUrl")+" | "+resource.getIdBase() + "("+resource.fhirType()+")"; + } + + public String getIndex() { + return Integer.toString(index); } } \ No newline at end of file