From c7e8ffff0990f07f30d1fc3b337913d595247704 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 31 Aug 2020 13:22:42 +1000 Subject: [PATCH] Add parent tracking for Validation support of nested bundles --- .../org/hl7/fhir/r5/elementmodel/Element.java | 20 +++++++++ .../org/hl7/fhir/utilities/Utilities.java | 27 ++++++++++++ .../instance/InstanceValidator.java | 41 +++++++++++++++---- 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index f5593fd81..a222778fe 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -100,6 +100,8 @@ public class Element extends Base { private SpecialElement special; private XhtmlNode xhtml; // if this is populated, then value will also hold the string representation private String explicitType; // for xsi:type attribute + private Element parentForValidator; + private boolean hasParentForValidator; public Element(String name) { super(); @@ -911,5 +913,23 @@ public class Element extends Base { return false; } + /** + * this is set by the instance validator. There's no reason to maintain this when working with an element tree, and so it should be ignored outside the validator + */ + public Element getParentForValidator() { + if (!hasParentForValidator) { + throw new Error("Parent not set"); + } + return parentForValidator; + } + + public void setParentForValidator(Element parentForValidator) { + this.parentForValidator = parentForValidator; + this.hasParentForValidator = true; + } + + public boolean hasParentForValidator() { + return hasParentForValidator; + } } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index 1b132bcc3..2015c3e22 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -57,6 +57,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeUnit; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -1369,4 +1370,30 @@ public class Utilities { return byteArrays; } + + public static String presentDuration(long duration) { + duration = duration / 1000000; + String res = ""; // ; + long days = TimeUnit.MILLISECONDS.toDays(duration); + long hours = TimeUnit.MILLISECONDS.toHours(duration) - + TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration)); + long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) - + TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration)); + long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) - + TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)); + long millis = TimeUnit.MILLISECONDS.toMillis(duration) - + TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration)); + + if (days > 0) + res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis); + else if (hours > 0) + res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis); + else // + res = String.format("%02d:%02d.%04d", minutes, seconds, millis); +// else +// res = String.format("%02d.%04d", seconds, millis); + return res; + } + + } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 94c87257a..48179bc5e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -238,19 +238,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } if (c.getAppContext() instanceof Element) { - Element bnd = (Element) c.getAppContext(); - Base res = resolveInBundle(url, bnd); - if (res != null) { - return res; + Element element = (Element) c.getAppContext(); + while (element != null) { + Base res = resolveInBundle(url, element); + if (res != null) { + return res; + } + element = element.getParentForValidator(); } } Base res = resolveInBundle(url, c.getResource()); if (res != null) { return res; } - res = resolveInBundle(url, c.getContainer()); - if (res != null) { - return res; + Element element = c.getRootResource(); + while (element != null) { + res = resolveInBundle(url, element); + if (res != null) { + return res; + } + element = element.getParentForValidator(); } if (externalHostServices != null) { @@ -279,6 +286,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (item instanceof Resource) { try { Element e = new ObjectConverter(context).convert((Resource) item); + setParents(e); self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, e, validationLanguage)); } catch (IOException e1) { throw new FHIRException(e1); @@ -682,6 +690,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat resourceTracker.clear(); executionId = UUID.randomUUID().toString(); baseOnly = profiles.isEmpty(); + setParents(element); long t = System.nanoTime(); if (profiles == null || profiles.isEmpty()) { @@ -697,6 +706,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat timeTracker.overall(t); } + private void checkElementUsage(List errors, Element element, NodeStack stack) { String elementUsage = element.getUserString("elementSupported"); hint(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), elementUsage == null || elementUsage.equals("Y"), I18nConstants.MUSTSUPPORT_VAL_MUSTSUPPORT, element.getName(), element.getProperty().getStructure().getUrl()); @@ -2418,6 +2428,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat throw new FHIRException(e); } if (ext != null) { + setParents(ext); fetchCache.put(ref, ext); } } @@ -3156,6 +3167,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return fetchCache.get(ref); } else { Element res = fetcher.fetch(appContext, ref); + setParents(res); fetchCache.put(ref, res); return res; } @@ -4903,5 +4915,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat this.noCheckAggregation = noCheckAggregation; } + + public static void setParents(Element element) { + if (element != null && !element.hasParentForValidator()) { + element.setParentForValidator(null); + setParentsInner(element); + } + } + public static void setParentsInner(Element element) { + for (Element child : element.getChildren()) { + child.setParentForValidator(element); + setParentsInner(child); + } + + } + } \ No newline at end of file