From 1c3061dbf7ddd44f4d8e4148a9925d7379d54ace Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 29 Jan 2020 13:39:49 +1100 Subject: [PATCH 01/44] track slice validation for users to resolve slicing issues --- .../validation/ValidationMessage.java | 10 +++ .../hl7/fhir/r5/validation/BaseValidator.java | 30 +++++-- .../fhir/r5/validation/InstanceValidator.java | 78 +++++++++++++++---- 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java index 85b94b619..c02a1643c 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java @@ -487,6 +487,7 @@ public class ValidationMessage implements Comparator, Compara private String html; private String locationLink; private String txLink; + private boolean slicingHint; /** @@ -746,5 +747,14 @@ public class ValidationMessage implements Comparator, Compara this.html = html; } + public boolean isSlicingHint() { + return slicingHint; + } + + public ValidationMessage setSlicingHint(boolean slicingHint) { + this.slicingHint = slicingHint; + return this; + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java index 9dc56c767..f8a3292a6 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java @@ -145,11 +145,32 @@ public class BaseValidator { */ protected boolean hint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg) { if (!thePass) { - addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION); + addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION); + } + return thePass; + } + + /** + * Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails. And mark it as a slicing hint for later recovery if appropriate + * + * @param thePass + * Set this parameter to false if the validation does not pass + * @return Returns thePass (in other words, returns true if the rule did not fail validation) + */ + protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg) { + if (!thePass) { + addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true); } return thePass; } + protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html) { + if (!thePass) { + addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true).setHtml(html); + } + return thePass; + } + /** * Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails * @@ -168,8 +189,7 @@ public class BaseValidator { protected boolean txHint(List errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { if (!thePass) { String message = formatMessage(theMessage, theMessageArguments); - addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine) - .setTxLink(txLink); + addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine).setTxLink(txLink); } return thePass; } @@ -338,9 +358,9 @@ public class BaseValidator { } - protected void addValidationMessage(List errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity) { + protected ValidationMessage addValidationMessage(List errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity) { Source source = this.source; - addValidationMessage(errors, type, line, col, path, msg, theSeverity, source); + return addValidationMessage(errors, type, line, col, path, msg, theSeverity, source); } protected ValidationMessage addValidationMessage(List errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 81ed1244a..489c3d6c7 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -207,6 +207,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private Element rootResource; private StructureDefinition profile; // the profile that contains the content being validated private boolean checkSpecials = true; + private Map> sliceRecords; public ValidatorHostContext(Object appContext) { this.appContext = appContext; @@ -242,6 +243,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat res.rootResource = rootResource; res.container = container; res.profile = profile; + res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap>(); return res; } @@ -276,6 +278,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat public Base getResource() { return resource; } + + public void sliceNotes(String url, List record) { + sliceRecords.put(url, record); + } + + public ValidatorHostContext forSlicing() { + ValidatorHostContext res = new ValidatorHostContext(appContext); + res.resource = resource; + res.rootResource = resource; + res.container = resource; + res.profile = profile; + res.checkSpecials = false; + res.sliceRecords = new HashMap>(); + return res; + } } @@ -405,8 +422,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } else throw new NotImplementedException("Not done yet (ValidatorHostServices.conformsToProfile), when item is not an element"); boolean ok = true; - for (ValidationMessage v : valerrors) + List record = new ArrayList<>(); + for (ValidationMessage v : valerrors) { ok = ok && !v.getLevel().isError(); + if (v.getLevel().isError() || v.isSlicingHint()) { + record.add(v); + } + } + if (!ok && !record.isEmpty()) { + ctxt.sliceNotes(url, record); + } return ok; } @@ -2353,7 +2378,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile())); for (StructureDefinition sd : badProfiles.keySet()) { - hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummary(badProfiles.get(sd))); + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummaryForSlicing(badProfiles.get(sd)), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); } } else { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size()==1, "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile())); @@ -2369,7 +2394,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet())); for (StructureDefinition sd : badProfiles.keySet()) { - hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummary(badProfiles.get(sd))); + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummaryForSlicing(badProfiles.get(sd)), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); } } else { warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet())); @@ -2434,16 +2459,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return true; } - private String errorSummary(List list) { + private String errorSummaryForSlicing(List list) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (ValidationMessage vm : list) { - if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL) { + if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL || vm.isSlicingHint()) { b.append(vm.getLocation()+": "+vm.getMessage()); } } return b.toString(); } + private String errorSummaryForSlicingAsHtml(List list) { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + for (ValidationMessage vm : list) { + if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL || vm.isSlicingHint()) { + b.append("
  • "+vm.getLocation()+": "+vm.getHtml()+"
  • "); + } + } + return "
      "+b.toString()+"
    "; + } + private TypeRefComponent getReferenceTypeRef(List types) { for (TypeRefComponent tr : types) { if ("Reference".equals(tr.getCode())) { @@ -3186,7 +3221,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat * @throws IOException * @throws FHIRException */ - private boolean sliceMatches(ValidatorHostContext hostContext, Element element, String path, ElementDefinition slicer, ElementDefinition ed, StructureDefinition profile, List errors, NodeStack stack) throws DefinitionException, FHIRException { + private boolean sliceMatches(ValidatorHostContext hostContext, Element element, String path, ElementDefinition slicer, ElementDefinition ed, StructureDefinition profile, List errors, List sliceInfo, NodeStack stack) throws DefinitionException, FHIRException { if (!slicer.getSlicing().hasDiscriminator()) return false; // cannot validate in this case @@ -3221,7 +3256,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } else throw new DefinitionException("Discriminator (" + discriminator + ") is based on type, but slice " + ed.getId() + " in "+profile.getUrl()+" has no types"); if (discriminator.isEmpty()) - expression.append(" and this is " + type); + expression.append(" and $this is " + type); else expression.append(" and " + discriminator + " is " + type); } else if (s.getType() == DiscriminatorType.PROFILE) { @@ -3281,7 +3316,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat ed.setUserData("slice.expression.cache", n); } - return evaluateSlicingExpression(hostContext, element, path, profile, n); + ValidatorHostContext shc = hostContext.forSlicing(); + boolean pass = evaluateSlicingExpression(shc, element, path, profile, n); + if (!pass) { + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Does not match slice'"+ed.getSliceName()+"' (discriminator = "+n.toString()+")"); + for (String url : shc.sliceRecords.keySet()) { + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+url+" does not match for "+stack.getLiteralPath()+" because of the following profile issues: "+errorSummaryForSlicing(shc.sliceRecords.get(url)), + "Profile "+url+" does not match for "+stack.getLiteralPath()+" because of the following profile issues: "+errorSummaryForSlicingAsHtml(shc.sliceRecords.get(url))); + } + } + return pass; } public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException { @@ -5018,7 +5062,10 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L // if (process) { for (ElementInfo ei : children) { - unsupportedSlicing = matchSlice(hostContext, errors, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei); + if (ei.sliceInfo == null) { + ei.sliceInfo = new ArrayList<>(); + } + unsupportedSlicing = matchSlice(hostContext, errors, ei.sliceInfo, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei); } // } } @@ -5032,9 +5079,11 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L if (ei.additionalSlice && ei.definition != null) { if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) || ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) { - hint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for the profile " + profile.getUrl())); + slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicing(ei.sliceInfo)), + "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicingAsHtml(ei.sliceInfo))); } else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) { - rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for profile " + profile.getUrl() + " and slicing is CLOSED")); + rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicing(ei.sliceInfo)), + "This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicingAsHtml(ei.sliceInfo))); } } else { // Don't raise this if we're in an abstract profile, like Resource @@ -5081,16 +5130,16 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element, onlyNonInherited); } - public boolean matchSlice(ValidatorHostContext hostContext, List errors, StructureDefinition profile, NodeStack stack, + public boolean matchSlice(ValidatorHostContext hostContext, List errors, List sliceInfo, StructureDefinition profile, NodeStack stack, ElementDefinition slicer, boolean unsupportedSlicing, List problematicPaths, int sliceOffset, int i, ElementDefinition ed, boolean childUnsupportedSlicing, ElementInfo ei) { boolean match = false; if (slicer == null || slicer == ed) { - match = nameMatches(ei.name, tail(ed.getPath())); + match = nameMatches(ei.name, tail(ed.getPath())); } else { if (nameMatches(ei.name, tail(ed.getPath()))) try { - match = sliceMatches(hostContext, ei.element, ei.path, slicer, ed, profile, errors, stack); + match = sliceMatches(hostContext, ei.element, ei.path, slicer, ed, profile, errors, sliceInfo, stack); if (match) { ei.slice = slicer; @@ -5557,6 +5606,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L public class ElementInfo { + public List sliceInfo; public int index; // order of definition in overall order. all slices get the index of the slicing definition public int sliceindex; // order of the definition in the slices (if slice != null) public int count; From e286d5b7bb2ea6b64c580fbcf9f7c760debff591 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 29 Jan 2020 13:40:22 +1100 Subject: [PATCH 02/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index c31501189..1c6294cc3 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index aa372157d..5a81da976 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 906fb23b3..1027e5fe1 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index bb2834b61..64658dcd2 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 9768fbd06..dbd164497 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index de7db29bc..f4fbdd2ad 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 59f79b22f..845ca5d03 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index a631cbfc4..29ca36df2 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 7d926f1ae..507257a42 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index dc73cad7e..2a1ba3c7b 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.54-SNAPSHOT + 4.1.55-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index 34f1e3689..13be697a6 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.53 -set newver=4.1.54 +set oldver=4.1.54 +set newver=4.1.55 echo .. echo ===================================================================== From 01c5789b89ce775e449b5bd1e00a428cb8e13736 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 29 Jan 2020 19:32:43 +1100 Subject: [PATCH 03/44] Deal with choices that constrain elements and not types --- .../fhir/r5/validation/InstanceValidator.java | 55 +++++++++++++++---- pom.xml | 2 +- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 489c3d6c7..790363d6b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -4674,16 +4674,14 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L if (childDefinitions.isEmpty()) { if (actualType == null) return; // there'll be an error elsewhere in this case, and we're going to stop. - StructureDefinition dt = null; - if (isAbsolute(actualType)) - dt = this.context.fetchResource(StructureDefinition.class, actualType); - else - dt = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + actualType); - if (dt == null) - throw new DefinitionException("Unable to resolve actual type " + actualType); - trackUsage(dt, hostContext, element); - - childDefinitions = ProfileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0)); + childDefinitions = getActualTypeChildren(hostContext, element, actualType); + } else if (definition.getType().size() > 1) { + // this only happens when the profile constrains the abstract children but leaves th choice open. + if (actualType == null) + return; // there'll be an error elsewhere in this case, and we're going to stop. + List typeChildDefinitions = getActualTypeChildren(hostContext, element, actualType); + // what were going to do is merge them - the type is not allowed to constrain things that the child definitions already do (well, if it does, it'll be ignored) + mergeChildLists(childDefinitions, typeChildDefinitions, definition.getPath(), actualType); } List children = listChildren(element, stack); @@ -4698,6 +4696,39 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L } } + private void mergeChildLists(List master, List additional, String masterPath, String typePath) { + for (ElementDefinition ed : additional) { + boolean inMaster = false; + for (ElementDefinition t : master) { + String tp = masterPath + ed.getPath().substring(typePath.length()); + if (t.getPath().equals(tp)) { + inMaster = true; + } + } + if (!inMaster) { + master.add(ed); + } + } + + + } + + // todo: the element definition in context might assign a constrained profile for the type? + public List getActualTypeChildren(ValidatorHostContext hostContext, Element element, String actualType) { + List childDefinitions; + StructureDefinition dt = null; + if (isAbsolute(actualType)) + dt = this.context.fetchResource(StructureDefinition.class, actualType); + else + dt = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + actualType); + if (dt == null) + throw new DefinitionException("Unable to resolve actual type " + actualType); + trackUsage(dt, hostContext, element); + + childDefinitions = ProfileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0)); + return childDefinitions; + } + public void checkChild(ValidatorHostContext hostContext, List errors, StructureDefinition profile, ElementDefinition definition, Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl) throws FHIRException, DefinitionException { @@ -5079,7 +5110,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L if (ei.additionalSlice && ei.definition != null) { if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) || ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) { - slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicing(ei.sliceInfo)), + slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl())+": "+errorSummaryForSlicing(ei.sliceInfo), "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicingAsHtml(ei.sliceInfo))); } else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) { rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicing(ei.sliceInfo)), @@ -5088,7 +5119,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L } else { // Don't raise this if we're in an abstract profile, like Resource if (!profile.getAbstract()) - hint(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "Could not verify slice for profile " + profile.getUrl()); + rule(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "This element is not allowed by the profile "+profile.getUrl()); } // TODO: Should get the order of elements correct when parsing elements that are XML attributes vs. elements boolean isXmlAttr = false; diff --git a/pom.xml b/pom.xml index 2a1ba3c7b..d70b1253d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.1.0 - 1.0.35-SNAPSHOT + 1.0.36-SNAPSHOT org.hl7.fhir.core From 6242a70b683b0eb225824f76289860a3b014a5f7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 29 Jan 2020 19:33:18 +1100 Subject: [PATCH 04/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 1c6294cc3..edb651727 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 5a81da976..3a0ec44a9 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 1027e5fe1..b3530c7b9 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 64658dcd2..a0fbb9d1b 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index dbd164497..0a608925e 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index f4fbdd2ad..831a8c64e 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 845ca5d03..14e3becec 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 29ca36df2..534c9b69f 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 507257a42..c074386b5 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index d70b1253d..1e52b0664 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.55-SNAPSHOT + 4.1.56-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index 13be697a6..d2cf848d0 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.54 -set newver=4.1.55 +set oldver=4.1.55 +set newver=4.1.56 echo .. echo ===================================================================== From 408ceb17611728ae31336ec8387fe26b976ade35 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 30 Jan 2020 11:05:30 +1100 Subject: [PATCH 05/44] fix bug with sorting where derived profile is adding more slice constraints --- .../fhir/r5/conformance/ProfileUtilities.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index e2c3a3aaa..07bd1a5ac 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -4354,13 +4354,13 @@ public class ProfileUtilities extends TranslatingUtilities { @Override public int compare(ElementDefinitionHolder o1, ElementDefinitionHolder o2) { if (o1.getBaseIndex() == 0) - o1.setBaseIndex(find(o1.getSelf().getPath())); + o1.setBaseIndex(find(o1.getSelf().getPath(), true)); if (o2.getBaseIndex() == 0) - o2.setBaseIndex(find(o2.getSelf().getPath())); + o2.setBaseIndex(find(o2.getSelf().getPath(), true)); return o1.getBaseIndex() - o2.getBaseIndex(); } - private int find(String path) { + private int find(String path, boolean mandatory) { String op = path; int lc = 0; String actual = base+path.substring(prefixLength); @@ -4392,10 +4392,12 @@ public class ProfileUtilities extends TranslatingUtilities { throw new Error("Internal recursion detection: find() loop path recursion > "+MAX_RECURSION_LIMIT+" - check paths are valid (for path "+path+"/"+op+")"); } } - if (prefixLength == 0) - errors.add("Differential contains path "+path+" which is not found in the base"); - else - errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the base"); + if (mandatory) { + if (prefixLength == 0) + errors.add("Differential contains path "+path+" which is not found in the base"); + else + errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the base"); + } return 0; } @@ -4508,7 +4510,7 @@ public class ProfileUtilities extends TranslatingUtilities { private void sortElements(ElementDefinitionHolder edh, ElementDefinitionComparer cmp, List errors) throws FHIRException { if (edh.getChildren().size() == 1) // special case - sort needsto allocate base numbers, but there'll be no sort if there's only 1 child. So in that case, we just go ahead and allocated base number directly - edh.getChildren().get(0).baseIndex = cmp.find(edh.getChildren().get(0).getSelf().getPath()); + edh.getChildren().get(0).baseIndex = cmp.find(edh.getChildren().get(0).getSelf().getPath(), false); else Collections.sort(edh.getChildren(), cmp); cmp.checkForErrors(errors); From c7f3a47ec911c4398b3924557f0935226a349ed6 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 30 Jan 2020 11:05:54 +1100 Subject: [PATCH 06/44] better rendering of slicing logic --- .../hl7/fhir/utilities/validation/ValidationMessage.java | 9 +++++++++ .../java/org/hl7/fhir/r5/validation/BaseValidator.java | 8 +------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java index c02a1643c..fe28e6cb4 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java @@ -487,6 +487,7 @@ public class ValidationMessage implements Comparator, Compara private String html; private String locationLink; private String txLink; + public String sliceHtml; private boolean slicingHint; @@ -756,5 +757,13 @@ public class ValidationMessage implements Comparator, Compara return this; } + public String getSliceHtml() { + return sliceHtml; + } + + public void setSliceHtml(String sliceHtml) { + this.sliceHtml = sliceHtml; + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java index f8a3292a6..81735d662 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/BaseValidator.java @@ -157,16 +157,10 @@ public class BaseValidator { * Set this parameter to false if the validation does not pass * @return Returns thePass (in other words, returns true if the rule did not fail validation) */ - protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg) { - if (!thePass) { - addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true); - } - return thePass; - } protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html) { if (!thePass) { - addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true).setHtml(html); + addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true).setSliceHtml(html); } return thePass; } From d807becebb1e9f30e4b381dbb89a52ba1ceb3159 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 30 Jan 2020 11:08:12 +1100 Subject: [PATCH 07/44] improve slicing hints and fix validation of FHIRPath URLs --- .../fhir/r5/validation/InstanceValidator.java | 25 ++++++++++++------- pom.xml | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 790363d6b..ba35d8a97 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -1622,9 +1622,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat Set allowedTypes = listExtensionTypes(ex); String actualType = getExtensionType(element); if (actualType == null) - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", allowedTypes.isEmpty(), "The Extension '" + url + "' definition is for a simple extension, so it must contain a value, not extensions"); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowedTypes.isEmpty(), "The Extension '" + url + "' definition is for a simple extension, so it must contain a value, not extensions"); else - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", allowedTypes.contains(actualType), "The Extension '" + url + "' definition allows for the types "+allowedTypes.toString()+" but found type "+actualType); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowedTypes.contains(actualType), "The Extension '" + url + "' definition allows for the types "+allowedTypes.toString()+" but found type "+actualType); // 3. is the content of the extension valid? validateElement(hostContext, errors, ex, ex.getSnapshot().getElement().get(0), null, null, resource, element, "Extension", stack, false, true, url); @@ -1984,7 +1984,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (fetcher != null) { boolean found; try { - found = (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url); + found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url); } catch (IOException e1) { found = false; } @@ -2147,6 +2147,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat // for nothing to check } + private boolean isDefinitionURL(String url) { + return Utilities.existsInList(url, "http://hl7.org/fhirpath/System.Boolean", "http://hl7.org/fhirpath/System.String", "http://hl7.org/fhirpath/System.Integer", + "http://hl7.org/fhirpath/System.Decimal", "http://hl7.org/fhirpath/System.Date", "http://hl7.org/fhirpath/System.Time", "http://hl7.org/fhirpath/System.DateTime", "http://hl7.org/fhirpath/System.Quantity"); + } + private void checkInnerNames(List errors, Element e, String path, List list) { for (XhtmlNode node : list) { if (node.getNodeType() == NodeType.Element) { @@ -2378,7 +2383,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile())); for (StructureDefinition sd : badProfiles.keySet()) { - slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummaryForSlicing(badProfiles.get(sd)), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+ref+" matching against Profile"+sd.getUrl(), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); } } else { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size()==1, "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile())); @@ -2394,7 +2399,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet())); for (StructureDefinition sd : badProfiles.keySet()) { - slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummaryForSlicing(badProfiles.get(sd)), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+ref+" matching against Profile"+sd.getUrl(), errorSummaryForSlicingAsHtml(badProfiles.get(sd))); } } else { warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet())); @@ -2472,7 +2477,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private String errorSummaryForSlicingAsHtml(List list) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (ValidationMessage vm : list) { - if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL || vm.isSlicingHint()) { + if (vm.isSlicingHint()) { + b.append("
  • "+vm.getLocation()+": "+vm.getSliceHtml()+"
  • "); + } else if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL ) { b.append("
  • "+vm.getLocation()+": "+vm.getHtml()+"
  • "); } } @@ -3319,9 +3326,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat ValidatorHostContext shc = hostContext.forSlicing(); boolean pass = evaluateSlicingExpression(shc, element, path, profile, n); if (!pass) { - slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Does not match slice'"+ed.getSliceName()+"' (discriminator = "+n.toString()+")"); + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Does not match slice'"+ed.getSliceName(), "discriminator = "+Utilities.escapeXml(n.toString())); for (String url : shc.sliceRecords.keySet()) { - slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+url+" does not match for "+stack.getLiteralPath()+" because of the following profile issues: "+errorSummaryForSlicing(shc.sliceRecords.get(url)), + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+stack.getLiteralPath()+" against profile "+url, "Profile "+url+" does not match for "+stack.getLiteralPath()+" because of the following profile issues: "+errorSummaryForSlicingAsHtml(shc.sliceRecords.get(url))); } } @@ -5110,7 +5117,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L if (ei.additionalSlice && ei.definition != null) { if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) || ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) { - slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl())+": "+errorSummaryForSlicing(ei.sliceInfo), + slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()), "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicingAsHtml(ei.sliceInfo))); } else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) { rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicing(ei.sliceInfo)), diff --git a/pom.xml b/pom.xml index 1e52b0664..adbbc394f 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.1.0 - 1.0.36-SNAPSHOT + 1.0.37-SNAPSHOT org.hl7.fhir.core From 1831d1954146090332d9c80fa33f3a22a0f33214 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 30 Jan 2020 11:09:52 +1100 Subject: [PATCH 08/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index edb651727..aef13bfb5 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 3a0ec44a9..86db9d29a 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index b3530c7b9..9ef346d8a 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index a0fbb9d1b..1b45e04a3 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 0a608925e..d44c1700d 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 831a8c64e..01a572720 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 14e3becec..81768d2b3 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 534c9b69f..8b22cdded 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index c074386b5..380341b0c 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index adbbc394f..46759e421 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.56-SNAPSHOT + 4.1.57-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index d2cf848d0..1218784b7 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.55 -set newver=4.1.56 +set oldver=4.1.56 +set newver=4.1.57 echo .. echo ===================================================================== From 5d1cf89db535d9324a3d8bac33686e88bc67539e Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 31 Jan 2020 08:19:51 +1100 Subject: [PATCH 09/44] add more package maintenance features --- .../hl7/fhir/utilities/cache/NpmPackage.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java index e3ae236b8..ed14e3f35 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java @@ -756,5 +756,23 @@ public class NpmPackage { Collections.sort(res); return res ; } + + public void clearFolder(String folderName) { + NpmPackageFolder folder = folders.get(folderName); + folder.content.clear(); + folder.types.clear(); + } + + public void deleteFolder(String folderName) { + folders.remove(folderName); + } + + public void addFile(String folderName, String name, byte[] cnt, String type) { + NpmPackageFolder folder = folders.get(folderName); + folder.content.put(name, cnt); + if (!folder.types.containsKey(type)) + folder.types.put(type, new ArrayList<>()); + folder.types.get(type).add(name); + } } From 6e9fd79a2adef89cca1fbc2972bed19d562215a0 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 31 Jan 2020 08:20:33 +1100 Subject: [PATCH 10/44] Add support for assumeValidRestReferences --- .../fhir/r5/validation/InstanceValidator.java | 16 ++++++++++++++++ .../hl7/fhir/r5/validation/ValidationEngine.java | 6 ++++++ .../org/hl7/fhir/r5/validation/Validator.java | 6 ++++++ .../validation/tests/ValidationTestSuite.java | 4 +++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index ba35d8a97..738105a92 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -156,6 +156,9 @@ import ca.uhn.fhir.util.ObjectUtil; * Thinking of using this in a java program? Don't! * You should use one of the wrappers instead. Either in HAPI, or use ValidationEngine * + * Validation todo: + * - support @default slices + * * @author Grahame Grieve * */ @@ -2434,6 +2437,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat boolean okToRef = !type.hasAggregation() || type.hasAggregation(AggregationMode.REFERENCED); rule(errors, IssueType.REQUIRED, -1, -1, path, okToRef, "Bundled or contained reference not found within the bundle/resource " + ref); } + if (we == null && ft != null && assumeValidRestReferences) { + // if we == null, we inferred ft from the reference. if we are told to treat this as gospel + TypeRefComponent type = getReferenceTypeRef(container.getType()); + Set types = new HashSet<>(); + for (CanonicalType tp : type.getTargetProfile()) { + StructureDefinition sd = context.fetchResource(StructureDefinition.class, tp.getValue()); + if (sd != null) { + types.add(sd.getType()); + } + } + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || types.contains(ft), "The type '"+ft+"' implied by the reference URL "+ref+" is not a valid Target for this element (must be one of "+types+")"); + + } if (pol == ReferenceValidationPolicy.CHECK_VALID) { // todo.... } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java index e2cd2093d..f0cbdc4f9 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java @@ -241,6 +241,7 @@ public class ValidationEngine implements IValidatorResourceFetcher { private boolean debug; private Set loadedIgs = new HashSet<>(); private IValidatorResourceFetcher fetcher; + private boolean assumeValidRestReferences; private class AsteriskFilter implements FilenameFilter { String dir; @@ -1270,6 +1271,7 @@ public class ValidationEngine implements IValidatorResourceFetcher { validator.setAnyExtensionsAllowed(anyExtensionsAllowed); validator.setNoInvariantChecks(isNoInvariantChecks()); validator.setValidationLanguage(language); + validator.setAssumeValidRestReferences(assumeValidRestReferences); validator.setFetcher(this); return validator; } @@ -1689,6 +1691,10 @@ public class ValidationEngine implements IValidatorResourceFetcher { this.fetcher = fetcher; } + public void setAssumeValidRestReferences(boolean assumeValidRestReferences) { + this.assumeValidRestReferences = assumeValidRestReferences; + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/Validator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/Validator.java index bf4c3d31f..043f54ff1 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/Validator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/Validator.java @@ -217,6 +217,8 @@ public class Validator { System.out.println(" referenced implementation guides or profiles as errors. (Default is to only raise information messages.)"); System.out.println("-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not"); System.out.println(" marked as mustSupport=true. Useful to identify elements included that may be ignored by recipients"); + System.out.println("-assumeValidRestReferences: If present, assume that URLs that reference resources follow the RESTful URI pattern"); + System.out.println(" and it is safe to infer the type from the URL"); System.out.println(""); System.out.println("The validator also supports the param -proxy=[address]:[port] for if you use a proxy"); System.out.println(""); @@ -414,6 +416,7 @@ public class Validator { String fhirpath = null; String snomedCT = "900000000000207008"; boolean doDebug = false; + boolean assumeValidRestReferences = false; // load the parameters - so order doesn't matter for (int i = 0; i < args.length; i++) { @@ -447,6 +450,8 @@ public class Validator { questionnaires.add(args[++i]); } else if (args[i].equals("-native")) { doNative = true; + } else if (args[i].equals("-assumeValidRestReferences")) { + assumeValidRestReferences = true; } else if (args[i].equals("-debug")) { doDebug = true; } else if (args[i].equals("-sct")) { @@ -577,6 +582,7 @@ public class Validator { validator.setAnyExtensionsAllowed(anyExtensionsAllowed); validator.setLanguage(lang); validator.setSnomedExtension(snomedCT); + validator.setAssumeValidRestReferences(assumeValidRestReferences); IParser x; if (output != null && output.endsWith(".json")) diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java index 94f227698..66b5dd003 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java @@ -177,6 +177,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour } else { val.setAllowExamples(true); } + val.setAssumeValidRestReferences(content.has("assumeValidRestReferences") ? content.get("assumeValidRestReferences").getAsBoolean() : false); if (name.endsWith(".json")) val.validate(null, errors, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON); else @@ -199,7 +200,8 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour System.out.println("Name: " + name+" - profile : "+profile.get("source").getAsString()); v = content.has("version") ? content.get("version").getAsString() : Constants.VERSION; StructureDefinition sd = loadProfile(filename, contents, v, messages); - val.getContext().cacheResource(sd); + val.getContext().cacheResource(sd); + val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false); List errorsProfile = new ArrayList(); if (name.endsWith(".json")) val.validate(null, errorsProfile, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON, asSdList(sd)); From ca29fdf182695b179f1fd522b4eab2efcc5f7b20 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 31 Jan 2020 08:23:17 +1100 Subject: [PATCH 11/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 4 ++-- release.bat | 4 ++-- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index aef13bfb5..6e84bc78c 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 86db9d29a..f90bfb68d 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 9ef346d8a..3d0655d2f 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 1b45e04a3..6824ea7cf 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index d44c1700d..7e7164ee5 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 01a572720..e3650db4e 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 81768d2b3..e4a8216a5 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 8b22cdded..e3d414184 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 380341b0c..c290bdfc2 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 46759e421..7cdd3989b 100644 --- a/pom.xml +++ b/pom.xml @@ -13,11 +13,11 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.57-SNAPSHOT + 4.1.58-SNAPSHOT 4.1.0 - 1.0.37-SNAPSHOT + 1.0.38-SNAPSHOT org.hl7.fhir.core diff --git a/release.bat b/release.bat index 1218784b7..793f4a22e 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.56 -set newver=4.1.57 +set oldver=4.1.57 +set newver=4.1.58 echo .. echo ===================================================================== From 53fc5cf7702c8daf34ebd69d0b4b76d30dc5d938 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 2 Feb 2020 06:13:24 +1100 Subject: [PATCH 12/44] add logic to test capability statement --- .../fhir/r5/validation/InstanceValidator.java | 55 ++++++++++++++----- pom.xml | 2 +- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 738105a92..7c4d8b41e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -108,6 +108,7 @@ import org.hl7.fhir.r5.model.Range; import org.hl7.fhir.r5.model.Ratio; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.SampledData; +import org.hl7.fhir.r5.model.SearchParameter; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.ExtensionContextType; @@ -3585,22 +3586,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } if (checkSpecials) { - // specific known special validations - if (element.getType().equals("Bundle")) { - validateBundle(errors, element, stack); - } else if (element.getType().equals("Observation")) { - validateObservation(errors, element, stack); - } else if (element.getType().equals("Questionnaire")) { - validateQuestionannaire(errors, element, stack); - } else if (element.getType().equals("QuestionnaireResponse")) { - validateQuestionannaireResponse(hostContext, errors, element, stack); - } else if (element.getType().equals("CodeSystem")) { - validateCodeSystem(errors, element, stack); - } + checkSpecials(hostContext, errors, element, stack, checkSpecials); validateResourceRules(errors, element, stack); } } + public void checkSpecials(ValidatorHostContext hostContext, List errors, Element element, NodeStack stack, boolean checkSpecials) { + // specific known special validations + if (element.getType().equals("Bundle")) { + validateBundle(errors, element, stack, checkSpecials); + } else if (element.getType().equals("Observation")) { + validateObservation(errors, element, stack); + } else if (element.getType().equals("Questionnaire")) { + validateQuestionannaire(errors, element, stack); + } else if (element.getType().equals("QuestionnaireResponse")) { + validateQuestionannaireResponse(hostContext, errors, element, stack); + } else if (element.getType().equals("CapabilityStatement")) { + validateCapabilityStatement(errors, element, stack); + } else if (element.getType().equals("CodeSystem")) { + validateCodeSystem(errors, element, stack); + } + } + private ResourceValidationTracker getResourceTracker(Element element) { ResourceValidationTracker res = resourceTracker.get(element); if (res == null) { @@ -3729,6 +3736,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } + private void validateCapabilityStatement(List errors, Element cs, NodeStack stack) { + int iRest = 0; + for (Element rest : cs.getChildrenByName("rest")) { + int iResource = 0; + for (Element resource : rest.getChildrenByName("resource")) { + int iSP = 0; + for (Element searchParam : resource.getChildrenByName("searchParam")) { + String ref = searchParam.getChildValue("definition"); + String type = searchParam.getChildValue("type"); + SearchParameter sp = context.fetchResource(SearchParameter.class, ref); + if (sp != null) { + rule(errors, IssueType.INVALID, searchParam.line(), searchParam.col(), stack.literalPath+".rest["+iRest+"].resource["+iResource+"].searchParam["+iSP+"]", + sp.getType().toCode().equals(type), "Type mismatch - SearchParameter '"+sp.getUrl()+"' type is "+sp.getType().toCode()+", but type here is "+type); + } + iSP++; + } + iResource++; + } + iRest++; + } + } private void validateCodeSystem(List errors, Element cs, NodeStack stack) { String url = cs.getNamedChildValue("url"); String vsu = cs.getNamedChildValue("valueSet"); @@ -4314,7 +4342,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L return true; } - private void validateBundle(List errors, Element bundle, NodeStack stack) { + private void validateBundle(List errors, Element bundle, NodeStack stack, boolean checkSpecials) { List entries = new ArrayList(); bundle.getNamedChildren("entry", entries); String type = bundle.getNamedChildValue("type"); @@ -4358,6 +4386,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), false, "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless the resource id ("+id+") also matches"); rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild("resource").fhirType(), id))), "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless on the canonical server itself"); } + // todo: check specials } } diff --git a/pom.xml b/pom.xml index 7cdd3989b..289679f7d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.1.0 - 1.0.38-SNAPSHOT + 1.0.39-SNAPSHOT org.hl7.fhir.core From b112b82951df8c828259c56ec6a31c6b99f66bde Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 2 Feb 2020 06:13:54 +1100 Subject: [PATCH 13/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 6e84bc78c..2cbe133da 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index f90bfb68d..fe3c065f4 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 3d0655d2f..abf242278 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 6824ea7cf..243bacfad 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 7e7164ee5..cdeb1a821 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index e3650db4e..a6be660a1 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index e4a8216a5..b82be69fc 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index e3d414184..3a64af411 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index c290bdfc2..e208e0159 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 289679f7d..4d5416f4e 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.58-SNAPSHOT + 4.1.59-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index 793f4a22e..c25970681 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.57 -set newver=4.1.58 +set oldver=4.1.58 +set newver=4.1.59 echo .. echo ===================================================================== From df9e11c40aaff6bf3b68b216956c916424a2054d Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 2 Feb 2020 22:52:43 +1100 Subject: [PATCH 14/44] fix bug in validator on search params with no references + fix bug in cache manager on github urls --- .../hl7/fhir/utilities/cache/PackageCacheManager.java | 6 ++++++ .../org/hl7/fhir/r5/validation/InstanceValidator.java | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java index 23c472ab9..36bd34736 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java @@ -316,6 +316,9 @@ public class PackageCacheManager { save = checkIniHasMapping("hl7.fhir.core", "http://hl7.org/fhir", ini) || save; save = checkIniHasMapping("hl7.fhir.pubpack", "http://fhir.org/packages/hl7.fhir.pubpack", ini) || save; save = checkIniHasMapping("hl7.fhir.xver-extensions", "http://fhir.org/packages/hl7.fhir.xver-extensions", ini) || save; + save = checkIniHasMapping("fhir.base.template", "http://fhir.org/templates/fhir.base.template", ini) || save; + save = checkIniHasMapping("hl7.base.template", "http://fhir.org/templates/hl7.base.template", ini) || save; + save = checkIniHasMapping("hl7.fhir.template", "http://fhir.org/templates/hl7.fhir.template", ini) || save; save = checkIniHasMapping("hl7.fhir.r2.core", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.core.tgz", ini) || save; save = checkIniHasMapping("hl7.fhir.r2.examples", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.examples.tgz", ini) || save; @@ -382,6 +385,9 @@ public class PackageCacheManager { public void recordMap(String url, String id) throws IOException { if (url == null) return; + if (url.contains("github.com")) { + return; + } if (!(new File(Utilities.path(cacheFolder, "packages.ini")).exists())) throw new Error("File "+Utilities.path(cacheFolder, "packages.ini")+" not found #1"); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 7c4d8b41e..4940545de 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -3745,10 +3745,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat for (Element searchParam : resource.getChildrenByName("searchParam")) { String ref = searchParam.getChildValue("definition"); String type = searchParam.getChildValue("type"); - SearchParameter sp = context.fetchResource(SearchParameter.class, ref); - if (sp != null) { - rule(errors, IssueType.INVALID, searchParam.line(), searchParam.col(), stack.literalPath+".rest["+iRest+"].resource["+iResource+"].searchParam["+iSP+"]", - sp.getType().toCode().equals(type), "Type mismatch - SearchParameter '"+sp.getUrl()+"' type is "+sp.getType().toCode()+", but type here is "+type); + if (!Utilities.noString(ref)) { + SearchParameter sp = context.fetchResource(SearchParameter.class, ref); + if (sp != null) { + rule(errors, IssueType.INVALID, searchParam.line(), searchParam.col(), stack.literalPath+".rest["+iRest+"].resource["+iResource+"].searchParam["+iSP+"]", + sp.getType().toCode().equals(type), "Type mismatch - SearchParameter '"+sp.getUrl()+"' type is "+sp.getType().toCode()+", but type here is "+type); + } } iSP++; } From 2732ef3dd501f6fa5be6fad5a0edb6e2662a79fb Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 2 Feb 2020 23:12:05 +1100 Subject: [PATCH 15/44] Release new version --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 2cbe133da..9d207adf6 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index fe3c065f4..d3b7ac53b 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index abf242278..112e890eb 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 243bacfad..728e9f6ea 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index cdeb1a821..7af2adffe 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index a6be660a1..a58504721 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index b82be69fc..037c01ce8 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 3a64af411..d7df05002 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index e208e0159..efd74e528 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 4d5416f4e..ad82f3701 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.59-SNAPSHOT + 4.1.60-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index c25970681..595c60a70 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.58 -set newver=4.1.59 +set oldver=4.1.59 +set newver=4.1.60 echo .. echo ===================================================================== From 6e2b58a4beda8007e0eb2686f158761e8c2e3529 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 5 Feb 2020 20:10:52 -0500 Subject: [PATCH 16/44] Remove debug code --- .../java/org/hl7/fhir/r5/validation/InstanceValidator.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index d2e0a20cd..b7ba0b684 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -4536,9 +4536,6 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L // time = System.nanoTime(); // check type invariants - if (definition.getId().equals("Composition.section:sectionResults")) { - System.out.println("!"); - } checkInvariants(hostContext, errors, profile, definition, resource, element, stack, false); if (definition.getFixed() != null) checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getUrl(), definition.getSliceName(), null); From 076ee562e3647117e9d1374e4a9e88204ac54b64 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 6 Feb 2020 11:16:17 -0500 Subject: [PATCH 17/44] Avoid trying to fetch SD by null URL (test case added) --- .../java/org/hl7/fhir/r5/validation/InstanceValidator.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 2e831205c..5accd1aef 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -1720,7 +1720,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat ok = true; break; } - sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); + if (sd.getBaseDefinition() != null) { + sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); + } else { + sd = null; + } } } } From 139cd561df8fae44a0b9a95834a0cb99b2896c05 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Feb 2020 10:27:52 +1100 Subject: [PATCH 18/44] Snapshot generation: handle profiles on Bundle.entry.resource properly --- .../fhir/r5/conformance/ProfileUtilities.java | 153 +++++++++++------- 1 file changed, 93 insertions(+), 60 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 07bd1a5ac..130946780 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -905,7 +905,7 @@ public class ProfileUtilities extends TranslatingUtilities { result.getElement().add(outcome); baseCursor++; diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1; - if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it + if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || isBaseResource(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it if (pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".") && !baseWalksInto(base.getElement(), baseCursor)) { if (outcome.getType().size() > 1) { if (outcome.getPath().endsWith("[x]") && !diffMatches.get(0).getPath().endsWith("[x]")) { @@ -1540,6 +1540,18 @@ public class ProfileUtilities extends TranslatingUtilities { } + private boolean isBaseResource(List types) { + if (types.isEmpty()) + return false; + for (TypeRefComponent type : types) { + String t = type.getWorkingCode(); + if ("Resource".equals(t)) + return false; + } + return true; + + } + public String determineFixedType(List diffMatches, String fixedType, int i) { if (diffMatches.get(i).getType().size() == 0 && diffMatches.get(i).hasSliceName()) { String n = tail(diffMatches.get(i).getPath()).replace("[x]", ""); @@ -2441,62 +2453,7 @@ public class ProfileUtilities extends TranslatingUtilities { if (!Base.compareDeep(derived.getType(), base.getType(), false)) { if (base.hasType()) { for (TypeRefComponent ts : derived.getType()) { - boolean ok = false; - CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - String t = ts.getWorkingCode(); - for (TypeRefComponent td : base.getType()) {; - String tt = td.getWorkingCode(); - b.append(tt); - if (td.hasCode() && (tt.equals(t))) { - ok = true; - } - if (!ok) { - StructureDefinition sdt = context.fetchTypeDefinition(tt); - if (sdt != null && sdt.getAbstract()) { - StructureDefinition sdb = context.fetchTypeDefinition(t); - while (sdb != null && !ok) { - ok = sdb.getType().equals(sdt.getUrl()); - sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition()); - } - } - } - // work around for old badly generated SDs - if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) { - ok = true; - } - if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) { - ok = true; - } - if (ok && ts.hasTargetProfile()) { - // check that any derived target has a reference chain back to one of the base target profiles - for (UriType u : ts.getTargetProfile()) { - String url = u.getValue(); - boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url); - while (url != null && !tgtOk) { - StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); - if (sd == null) { - if (messages != null) { - messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); - } - url = null; - tgtOk = true; // suppress error message - } else { - url = sd.getBaseDefinition(); - tgtOk = td.hasTargetProfile(url); - } - } - if (!tgtOk) { - if (messages == null) { - throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")"); - } else { - messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR)); - } - } - } - } - } - if (!ok) - throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl()); + checkTypeDerivation(purl, srcSD, base, derived, ts); } } base.getType().clear(); @@ -2576,6 +2533,66 @@ public class ProfileUtilities extends TranslatingUtilities { } } + public void checkTypeDerivation(String purl, StructureDefinition srcSD, ElementDefinition base, ElementDefinition derived, TypeRefComponent ts) { + boolean ok = false; + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + String t = ts.getWorkingCode(); + for (TypeRefComponent td : base.getType()) {; + String tt = td.getWorkingCode(); + b.append(tt); + if (td.hasCode() && (tt.equals(t))) { + ok = true; + } + if (!ok) { + StructureDefinition sdt = context.fetchTypeDefinition(tt); + if (sdt != null && sdt.getAbstract()) { + StructureDefinition sdb = context.fetchTypeDefinition(t); + while (sdb != null && !ok) { + ok = sdb.getType().equals(sdt.getType()); + sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition()); + } + } + } + // work around for old badly generated SDs + if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) { + ok = true; + } + if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) { + ok = true; + } + if (ok && ts.hasTargetProfile()) { + // check that any derived target has a reference chain back to one of the base target profiles + for (UriType u : ts.getTargetProfile()) { + String url = u.getValue(); + boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url); + while (url != null && !tgtOk) { + StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); + if (sd == null) { + if (messages != null) { + messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); + } + url = null; + tgtOk = true; // suppress error message + } else { + url = sd.getBaseDefinition(); + tgtOk = td.hasTargetProfile(url); + } + } + if (!tgtOk) { + if (messages == null) { + throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")"); + } else { + messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR)); + } + } + } + } + } + if (!ok) { + throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl()); + } + } + public void checkTypeOk(ElementDefinition dest, String ft) { boolean ok = false; @@ -4518,8 +4535,9 @@ public class ProfileUtilities extends TranslatingUtilities { for (ElementDefinitionHolder child : edh.getChildren()) { if (child.getChildren().size() > 0) { ElementDefinitionComparer ccmp = getComparer(cmp, child); - if (ccmp != null) - sortElements(child, ccmp, errors); + if (ccmp != null) { + sortElements(child, ccmp, errors); + } } } } @@ -4530,7 +4548,22 @@ public class ProfileUtilities extends TranslatingUtilities { ElementDefinition ed = cmp.snapshot.get(child.getBaseIndex()); ElementDefinitionComparer ccmp; if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) { - ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name); + if (ed.hasType() && "Resource".equals(ed.getType().get(0).getWorkingCode()) && child.getSelf().getType().get(0).hasProfile()) { + if (child.getSelf().getType().get(0).getProfile().size() > 1) { + throw new FHIRException("Unhandled situation: resource is profiled to more than one option - cannot sort profile"); + } + StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue()); + while (profile != null && profile.getDerivation() == TypeDerivationRule.CONSTRAINT) { + profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition()); + } + if (profile==null) { + ccmp = null; // this might happen before everything is loaded. And we don't so much care about sot order in this case + } else { + ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), profile.getType(), child.getSelf().getPath().length(), cmp.name); + } + } else { + ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name); + } } else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) { StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue()); if (profile==null) From b95a05045eeec760b1283d6afb201972732caf3f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Feb 2020 10:29:16 +1100 Subject: [PATCH 19/44] Improve error message when package can't be accessed --- .../utilities/cache/PackageCacheManager.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java index 36bd34736..be1f1f8f7 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java @@ -437,7 +437,7 @@ public class PackageCacheManager { String u = o.get("url").getAsString(); if (u.contains("/ImplementationGuide/")) u = u.substring(0, u.indexOf("/ImplementationGuide/")); - builds.add(new BuildRecord(u, o.get("package-id").getAsString(), o.get("repo").getAsString(), readDate(o.get("date").getAsString()))); + builds.add(new BuildRecord(u, o.get("package-id").getAsString(), getRepo(o.get("repo").getAsString()), readDate(o.get("date").getAsString()))); } } Collections.sort(builds, new BuildRecordSorter()); @@ -449,6 +449,11 @@ public class PackageCacheManager { } } + private String getRepo(String path) { + String[] p = path.split("\\/"); + return p[0]+"/"+p[1]; + } + private Date readDate(String s) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM, yyyy HH:mm:ss Z", new Locale("en", "US")); return sdf.parse(s); @@ -665,33 +670,42 @@ public class PackageCacheManager { } String url = getPackageUrl(id); - if (url == null) + if (url == null) { throw new FHIRException("Unable to resolve the package '"+id+"'"); + } + String aurl = null; + try { if (url.contains(".tgz")) { + aurl = url; InputStream stream = fetchFromUrlSpecific(url, true); if (stream != null) return addPackageToCache(id, v, stream, url); throw new FHIRException("Unable to find the package source for '"+id+"' at "+url); } if (v == null) { + aurl = Utilities.pathURL(url, "package.tgz"); InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(url, "package.tgz"), true); if (stream == null && isBuildLoaded()) { + aurl = Utilities.pathURL(buildPath(url), "package.tgz"); stream = fetchFromUrlSpecific(Utilities.pathURL(buildPath(url), "package.tgz"), true); } if (stream != null) return addPackageToCache(id, null, stream, url); throw new FHIRException("Unable to find the package source for '"+id+"' at "+url); } else if ("current".equals(v) && ciList.containsKey(id)){ + aurl = Utilities.pathURL(buildPath(url), "package.tgz"); InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "package.tgz"), true); return addPackageToCache(id, v, stream, Utilities.pathURL(ciList.get(id), "package.tgz")); } else { String pu = Utilities.pathURL(url, "package-list.json"); + aurl = pu; JsonObject json; try { json = fetchJson(pu); } catch (Exception e) { String pv = Utilities.pathURL(url, v, "package.tgz"); try { + aurl = pv; InputStream stream = fetchFromUrlSpecific(pv, true); return addPackageToCache(id, v, stream, pv); } catch (Exception e1) { @@ -703,6 +717,7 @@ public class PackageCacheManager { for (JsonElement e : json.getAsJsonArray("list")) { JsonObject vo = (JsonObject) e; if (v.equals(JSONUtil.str(vo, "version"))) { + aurl = Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"); InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"), true); if (stream == null) throw new FHIRException("Unable to find the package source for '"+id+"#"+v+"' at "+Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz")); @@ -718,6 +733,9 @@ public class PackageCacheManager { // } throw new FHIRException("Unable to resolve version "+v+" for package "+id); } + } catch (Exception e) { + throw new FHIRException(e.getMessage()+(aurl == null ? "" : " (url = "+aurl+")"), e); + } } From c0976dd365c1b08d98b1aed3d19b87da164900a4 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Feb 2020 10:30:17 +1100 Subject: [PATCH 20/44] add support for [user] in path --- .../org/hl7/fhir/utilities/Utilities.java | 19 ++++++++++++++----- .../fhir/utilities/tests/UtilitiesTests.java | 18 ++++++++++++++++++ pom.xml | 2 +- release.bat | 3 ++- 4 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/UtilitiesTests.java 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 ce70b1bf4..7b5aba50b 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 @@ -568,11 +568,20 @@ public class Utilities { else if (!s.toString().endsWith(File.separator)) s.append(File.separator); String a = arg; - if ("[tmp]".equals(a)) { - if (hasCTempDir()) { - a = "c:\\temp"; - } else { - a = System.getProperty("java.io.tmpdir"); + if (s.length() == 0) { + if ("[tmp]".equals(a)) { + if (hasCTempDir()) { + a = "c:\\temp"; + } else { + a = System.getProperty("java.io.tmpdir"); + } + } else if ("[user]".equals(a)) { + a = System.getProperty("user.home"); + } else if (a.startsWith("[") && a.endsWith("]")){ + String ev = System.getenv(a.replace("[", "").replace("]", "")); + if (ev != null) { + a = ev; + } } } a = a.replace("\\", File.separator); diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/UtilitiesTests.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/UtilitiesTests.java new file mode 100644 index 000000000..a7cc47ca1 --- /dev/null +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/UtilitiesTests.java @@ -0,0 +1,18 @@ +package org.hl7.fhir.utilities.tests; + +import java.io.IOException; + +import org.hl7.fhir.utilities.Utilities; +import org.junit.Test; + +import junit.framework.Assert; + +public class UtilitiesTests { + + @Test + public void testPath() throws IOException { + Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), "c:\\temp\\test.txt"); + Assert.assertEquals(Utilities.path("[user]", "test.txt"), System.getProperty("user.home")+"\\test.txt"); + Assert.assertEquals(Utilities.path("[JAVA_HOME]", "test.txt"), System.getenv("JAVA_HOME")+"\\test.txt"); + } +} diff --git a/pom.xml b/pom.xml index ad82f3701..8b2d954ec 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.1.0 - 1.0.39-SNAPSHOT + 1.0.40-SNAPSHOT org.hl7.fhir.core diff --git a/release.bat b/release.bat index 595c60a70..269b7b3ac 100644 --- a/release.bat +++ b/release.bat @@ -11,7 +11,8 @@ echo .. call mvn versions:set -DnewVersion=%newver%-SNAPSHOT -call git commit -a -m "Release new version" +call git commit -t v%newver% -a -m "Release new version %newver%" + call git push origin master call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\build" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 8 call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\fhir-ig-publisher" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 2 From b6ba504320f6b3bb44adf23915baf513bd4cd190 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Feb 2020 10:55:06 +1100 Subject: [PATCH 21/44] Release new version 4.1.61 --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 9d207adf6..54bfb1e60 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index d3b7ac53b..e1e64e41c 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 112e890eb..698148ecc 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 728e9f6ea..6fab60a00 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 7af2adffe..4a8780c47 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index a58504721..fd5b7344f 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 037c01ce8..8edfda25a 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index d7df05002..4b09629e3 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index efd74e528..c3dde4566 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 8b2d954ec..a9e69270e 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.60-SNAPSHOT + 4.1.61-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index 269b7b3ac..faeeeb68c 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.59 -set newver=4.1.60 +set oldver=4.1.60 +set newver=4.1.61 echo .. echo ===================================================================== From 398dbb003c250d5934af55fa2a47759775b5dee2 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Feb 2020 12:10:32 +1100 Subject: [PATCH 22/44] fix IHE template --- .../java/org/hl7/fhir/utilities/cache/PackageCacheManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java index be1f1f8f7..e8d562ed2 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java @@ -319,6 +319,7 @@ public class PackageCacheManager { save = checkIniHasMapping("fhir.base.template", "http://fhir.org/templates/fhir.base.template", ini) || save; save = checkIniHasMapping("hl7.base.template", "http://fhir.org/templates/hl7.base.template", ini) || save; save = checkIniHasMapping("hl7.fhir.template", "http://fhir.org/templates/hl7.fhir.template", ini) || save; + save = checkIniHasMapping("ihe.fhir.template", "http://fhir.org/templates/ihe.fhir.template", ini) || save; save = checkIniHasMapping("hl7.fhir.r2.core", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.core.tgz", ini) || save; save = checkIniHasMapping("hl7.fhir.r2.examples", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.examples.tgz", ini) || save; From 4708fcb49ea24b23e350c37ed856be94a247a380 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 9 Feb 2020 08:14:30 +1100 Subject: [PATCH 23/44] add support for file: in package version (per NPM spec) --- .../java/org/hl7/fhir/r5/test/AllR5Tests.java | 3 +- .../org/hl7/fhir/r5/test/FHIRPathTests.java | 2 +- .../hl7/fhir/r5/test/PackageCacheTests.java | 36 ++++++++++++ .../org/hl7/fhir/r5/test/UtilitiesTests.java | 18 ++++++ .../org/hl7/fhir/utilities/Utilities.java | 16 ++++-- .../hl7/fhir/utilities/cache/NpmPackage.java | 46 ++++++++++++++- .../utilities/cache/PackageCacheManager.java | 57 ++++++++++++++++++- .../fhir/r5/validation/ValidationEngine.java | 2 +- pom.xml | 2 +- release.bat | 9 ++- 10 files changed, 180 insertions(+), 11 deletions(-) create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageCacheTests.java create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java index 5d10d4150..5a06dbc76 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java @@ -7,6 +7,7 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ + NpmPackageTests.class, SnomedExpressionsTests.class, GraphQLParserTests.class, TurtleTests.class, @@ -21,7 +22,7 @@ import org.junit.runners.Suite.SuiteClasses; BaseDateTimeTypeTest.class, OpenApiGeneratorTest.class, MetadataResourceManagerTester.class, - NpmPackageTests.class, + UtilitiesTests.class, SnapShotGenerationTests.class}) public class AllR5Tests { diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java index 79bfc1180..e9ca3d568 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRPathTests.java @@ -102,7 +102,7 @@ public class FHIRPathTests { @Parameters(name = "{index}: file {0}") public static Iterable data() throws ParserConfigurationException, SAXException, IOException { - Document dom = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fhirpath", "tests-fhir-r4.xml")); + Document dom = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fhirpath", "tests-fhir-r5.xml")); List list = new ArrayList(); List groups = new ArrayList(); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageCacheTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageCacheTests.java new file mode 100644 index 000000000..8b798a839 --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageCacheTests.java @@ -0,0 +1,36 @@ +package org.hl7.fhir.r5.test; + +import java.io.File; +import java.io.IOException; + +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.cache.NpmPackage; +import org.hl7.fhir.utilities.cache.PackageCacheManager; +import org.hl7.fhir.utilities.cache.ToolsVersion; +import org.junit.Assert; +import org.junit.Test; + +public class PackageCacheTests { + + @Test + public void testPath() throws IOException { + PackageCacheManager cache = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION); + cache.clear(); + NpmPackage npm = cache.loadPackage("hl7.fhir.pubpack", "0.0.3"); + npm.loadAllFiles(); + Assert.assertNotNull(npm); + File dir = new File(Utilities.path("[tmp]", "cache")); + if (dir.exists()) { + Utilities.clearDirectory(dir.getAbsolutePath()); + } else { + Utilities.createDirectory(dir.getAbsolutePath()); + } + npm.save(dir); + NpmPackage npm2 = cache.loadPackage("hl7.fhir.pubpack", "file:"+dir.getAbsolutePath()); + Assert.assertNotNull(npm2); + + } + + +} + diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java new file mode 100644 index 000000000..66c4416a9 --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java @@ -0,0 +1,18 @@ +package org.hl7.fhir.r5.test; + +import java.io.IOException; + +import org.hl7.fhir.utilities.Utilities; +import org.junit.Test; + +import junit.framework.Assert; + +public class UtilitiesTests { + + @Test + public void testPath() throws IOException { + Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), "c:\\temp\\test.txt"); + Assert.assertEquals(Utilities.path("[user]", "test.txt"), System.getProperty("user.home")+"\\test.txt"); + Assert.assertEquals(Utilities.path("[JAVA_HOME]", "test.txt"), System.getenv("JAVA_HOME")+"\\test.txt"); + } +} 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 7b5aba50b..514f571fc 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 @@ -63,6 +63,7 @@ import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URLEncoder; import java.nio.channels.FileChannel; +import java.nio.file.Paths; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -590,11 +591,15 @@ public class Utilities { a = a.substring(File.separator.length()); while (a.startsWith(".."+File.separator)) { - String p = s.toString().substring(0, s.length()-1); - if (!p.contains(File.separator)) { - s = new StringBuilder(); + if (s.length() == 0) { + s = new StringBuilder(Paths.get(".").toAbsolutePath().normalize().toString()); } else { - s = new StringBuilder(p.substring(0, p.lastIndexOf(File.separator))+File.separator); + String p = s.toString().substring(0, s.length()-1); + if (!p.contains(File.separator)) { + s = new StringBuilder(); + } else { + s = new StringBuilder(p.substring(0, p.lastIndexOf(File.separator))+File.separator); + } } a = a.substring(3); } @@ -608,6 +613,9 @@ public class Utilities { } private static boolean hasCTempDir() { + if (!System.getProperty("os.name").toLowerCase().contains("win")) { + return false; + } File tmp = new File("c:\\temp"); return tmp.exists() && tmp.isDirectory(); } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java index ed14e3f35..6817c4c3e 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java @@ -186,7 +186,8 @@ public class NpmPackage { public static void loadFiles(NpmPackage res, String path, File source, String... exemptions) throws FileNotFoundException, IOException { res.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json"))); - + res.path = path; + File dir = new File(path); for (File f : dir.listFiles()) { if (!Utilities.existsInList(f.getName(), ".git", ".svn") && !Utilities.existsInList(f.getName(), exemptions)) { @@ -622,6 +623,37 @@ public class NpmPackage { return folders; } + public void save(File directory) throws IOException { + File dir = new File(Utilities.path(directory.getAbsolutePath(), name())); + if (!dir.exists()) { + Utilities.createDirectory(dir.getAbsolutePath()); + } else { + Utilities.clearDirectory(dir.getAbsolutePath()); + } + + for (NpmPackageFolder folder : folders.values()) { + String n = folder.name; + + File pd = new File(Utilities.path(dir.getAbsolutePath(), n)); + if (!pd.exists()) { + Utilities.createDirectory(pd.getAbsolutePath()); + } + NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder(); + indexer.start(); + for (String s : folder.content.keySet()) { + byte[] b = folder.content.get(s); + indexer.seeFile(s, b); + if (!s.equals(".index.json") && !s.equals("package.json")) { + TextFile.bytesToFile(b, Utilities.path(dir.getAbsolutePath(), n, s)); + } + } + byte[] cnt = indexer.build().getBytes(Charset.forName("UTF-8")); + TextFile.bytesToFile(cnt, Utilities.path(dir.getAbsolutePath(), n, ".index.json")); + } + byte[] cnt = TextFile.stringToBytes(new GsonBuilder().setPrettyPrinting().create().toJson(npm), false); + TextFile.bytesToFile(cnt, Utilities.path(dir.getAbsolutePath(), "package", "package.json")); + } + public void save(OutputStream stream) throws IOException { TarArchiveOutputStream tar; ByteArrayOutputStream OutputStream; @@ -774,5 +806,17 @@ public class NpmPackage { folder.types.put(type, new ArrayList<>()); folder.types.get(type).add(name); } + + public void loadAllFiles() throws IOException { + for (String folder : folders.keySet()) { + NpmPackageFolder pf = folders.get(folder); + String p = Utilities.path(path, folder); + for (File f : new File(p).listFiles()) { + if (!f.isDirectory()) { + pf.getContent().put(f.getName(), TextFile.fileToBytes(f)); + } + } + } + } } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java index e8d562ed2..c7c79d53f 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java @@ -268,8 +268,10 @@ public class PackageCacheManager { private void clearCache() throws IOException { for (File f : new File(cacheFolder).listFiles()) { - if (f.isDirectory()) + if (f.isDirectory()) { + Utilities.clearDirectory(f.getAbsolutePath()); FileUtils.deleteDirectory(f); + } else if (!f.getName().equals("packages.ini")) FileUtils.forceDelete(f); } @@ -552,6 +554,13 @@ public class PackageCacheManager { * @throws IOException */ public NpmPackage loadPackageFromCacheOnly(String id, String version) throws IOException { + if (Utilities.noString(version)) { + throw new FHIRException("Invalid version - ''"); + } + if (version.startsWith("file:")) { + return loadPackageFromFile(id, version.substring(5)); + } + for (NpmPackage p : temporaryPackages) { if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version))) return p; @@ -571,6 +580,7 @@ public class PackageCacheManager { * Add an already fetched package to the cache */ public NpmPackage addPackageToCache(String id, String version, InputStream tgz, String sourceDesc) throws IOException { + checkValidVersionString(version, id); if (progress ) { System.out.println("Installing "+id+"#"+(version == null ? "?" : version)+" to the package cache"); System.out.print(" Fetching:"); @@ -648,11 +658,31 @@ public class PackageCacheManager { return pck; } + private void checkValidVersionString(String version, String id) { + if (Utilities.noString(version)) { + throw new FHIRException("Cannot add package "+id+" to the package cache - a version must be provided"); + } + if (version.startsWith("file:")) { + throw new FHIRException("Cannot add package "+id+" to the package cache - the version '"+version+"' is illegal in this context"); + } + for (char ch : version.toCharArray()) { + if (!Character.isAlphabetic(ch) && !Character.isDigit(ch) && !Utilities.existsInList(ch, '.', '-')) { + throw new FHIRException("Cannot add package "+id+" to the package cache - the version '"+version+"' is illegal (ch '"+ch+"'"); + } + } + } + public NpmPackage loadPackage(String id) throws FHIRException, IOException { throw new Error("Not done yet"); } public NpmPackage loadPackage(String id, String v) throws FHIRException, IOException { + if (Utilities.noString(v)) { + throw new FHIRException("Invalid version - ''"); + } + if (v.startsWith("file:")) { + return loadPackageFromFile(id, v.substring(5)); + } NpmPackage p = loadPackageFromCacheOnly(id, v); if (p != null) { if ("current".equals(v)) { @@ -756,6 +786,16 @@ public class PackageCacheManager { * @return */ public boolean hasPackage(String id, String version) { + if (Utilities.noString(version)) { + throw new FHIRException("Invalid version - ''"); + } + if (version.startsWith("file:")) { + try { + return loadPackageFromFile(id, version.substring(5)) != null; + } catch (IOException e) { + return false; + } + } for (NpmPackage p : temporaryPackages) { if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version))) return true; @@ -772,6 +812,21 @@ public class PackageCacheManager { } + private NpmPackage loadPackageFromFile(String id, String folder) throws IOException { + File f = new File(Utilities.path(folder, id)); + if (!f.exists()) { + throw new FHIRException("Package '"+id+" not found in folder "+folder); + } + if (!f.isDirectory()) { + throw new FHIRException("File for '"+id+" found in folder "+folder+", not a folder"); + } + File fp = new File(Utilities.path(folder, id, "package", "package.json")); + if (!fp.exists()) { + throw new FHIRException("Package '"+id+" found in folder "+folder+", but does not contain a package.json file in /package"); + } + return NpmPackage.fromFolder(f.getAbsolutePath()); + } + /** * List which versions of a package are available * diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java index f0cbdc4f9..6a376f1ef 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java @@ -433,7 +433,7 @@ public class ValidationEngine implements IValidatorResourceFetcher { return fetchFromUrl(src+(v == null ? "" : "|"+v), explore); } - File f = new File(src); + File f = new File(Utilities.path(src)); if (f.exists()) { if (f.isDirectory() && new File(Utilities.path(src, "package.tgz")).exists()) return loadPackage(new FileInputStream(Utilities.path(src, "package.tgz")), Utilities.path(src, "package.tgz")); diff --git a/pom.xml b/pom.xml index a9e69270e..24c7b00bd 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 4.1.0 - 1.0.40-SNAPSHOT + 1.0.41-SNAPSHOT org.hl7.fhir.core diff --git a/release.bat b/release.bat index faeeeb68c..c322309bc 100644 --- a/release.bat +++ b/release.bat @@ -23,6 +23,9 @@ IF %ERRORLEVEL% NEQ 0 ( GOTO DONE ) +call "C:\tools\versionNotes.exe" -fileName C:\work\org.hl7.fhir\latest-ig-publisher\release-notes-validator.md -version %newver% -fileDest C:\temp\current-release-notes-validator.md -url https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar -maven https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=%newver%-SNAPSHOT&e=jar + + copy org.hl7.fhir.validation.cli\target\org.hl7.fhir.validation.cli-%newver%-SNAPSHOT.jar ..\latest-ig-publisher\org.hl7.fhir.validator.jar cd ..\latest-ig-publisher call git commit -a -m "Release new version %newver%-SNAPSHOT" @@ -30,7 +33,11 @@ call git push origin master cd ..\org.hl7.fhir.core call python c:\tools\zulip-api\zulip\zulip\send.py --stream committers/notification --subject "java core" -m "New Java Core v%newver%-SNAPSHOT released. New Validator at https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=%newver%-SNAPSHOT&e=jar, and also deployed at https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar" --config-file zuliprc -call python c:\tools\zulip-api\zulip\zulip\send.py --stream tooling/releases --subject "Validator" -m "New Validator @ https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar (v%newver%)" --config-file zuliprc +call python c:\tools\zulip-api\zulip\zulip\send.py --stream tooling/releases --subject "Validator" --config-file zuliprc < C:\temp\current-release-notes-validator.md + +del C:\temp\current-release-notes-validator.md + +pause :DONE echo =============================================================== From 9dc8b910c3dcd082194e57fdd54836402f30de23 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:36:37 +1100 Subject: [PATCH 24/44] fix problem with conversion of ElementDefinition between R3 and R5 --- .../hl7/fhir/convertors/VersionConvertor_30_50.java | 12 ++++++++++++ .../conv30_50/StructureDefinition30_50.java | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java index 65c7bf43f..7f6693c8c 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java @@ -328,6 +328,18 @@ public class VersionConvertor_30_50 { return tgt; } + public static org.hl7.fhir.r5.model.UriType convertCodeToUri(org.hl7.fhir.dstu3.model.CodeType src) throws FHIRException { + org.hl7.fhir.r5.model.UriType tgt = new org.hl7.fhir.r5.model.UriType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + + public static org.hl7.fhir.dstu3.model.CodeType convertUriToCode(org.hl7.fhir.r5.model.UriType src) throws FHIRException { + org.hl7.fhir.dstu3.model.CodeType tgt = new org.hl7.fhir.dstu3.model.CodeType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + public static org.hl7.fhir.r5.model.UuidType convertUuid(org.hl7.fhir.dstu3.model.UuidType src) throws FHIRException { org.hl7.fhir.r5.model.UuidType tgt = new org.hl7.fhir.r5.model.UuidType(src.getValue()); copyElement(src, tgt); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/StructureDefinition30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/StructureDefinition30_50.java index 2e1346654..738c8ed1a 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/StructureDefinition30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/StructureDefinition30_50.java @@ -175,8 +175,9 @@ public class StructureDefinition30_50 { if (src.hasAbstractElement()) tgt.setAbstractElement((org.hl7.fhir.dstu3.model.BooleanType) VersionConvertor_30_50.convertType(src.getAbstractElement())); for (org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionContextComponent t : src.getContext()) { - if (!tgt.hasContextType()) - tgt.setTypeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getTypeElement())); + if (!tgt.hasContextType()) { + tgt.setTypeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertUriToCode(src.getTypeElement())); + } tgt.addContext("Element".equals(t.getExpression()) ? "*" : t.getExpression()); } if (src.hasContextInvariant()) { From 6ec76df7fc7699f24e646f38cd1d204ab76a9b80 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:42:09 +1100 Subject: [PATCH 25/44] Fix generator to add both lang and xml:lang per https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + Fix the generator handle Concept Maps with missing tragets --- .../main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java index 4515cc637..0dd6c90d6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java @@ -2515,6 +2515,8 @@ public class NarrativeGenerator implements INarrativeGenerator { if (!x.hasAttribute("xmlns")) x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); if (r.hasLanguage()) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", r.getLanguage()); x.setAttribute("xml:lang", r.getLanguage()); } if (!r.hasText() || !r.getText().hasDiv() || r.getText().getDiv().getChildNodes().isEmpty()) { @@ -2919,6 +2921,9 @@ public class NarrativeGenerator implements INarrativeGenerator { } private ConceptMapRenderInstructions findByTarget(DataType source) { + if (source == null) { + return null; + } String src = source.primitiveValue(); if (src != null) for (ConceptMapRenderInstructions t : renderingMaps) { From 8e756de52e59e5c407c2e092992645c0e1670c91 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:43:44 +1100 Subject: [PATCH 26/44] handle test that has dep profile with unresolved dependencies --- .../src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java index 5a06dbc76..f6191b0f2 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java @@ -8,6 +8,7 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ NpmPackageTests.class, + PackageClientTests.class, SnomedExpressionsTests.class, GraphQLParserTests.class, TurtleTests.class, From 0f74f250783e0a4868ee4b18870ff7fb2ae2da23 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:44:19 +1100 Subject: [PATCH 27/44] Add more debugging for conversion failures --- .../main/java/org/hl7/fhir/r5/validation/ValidationEngine.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java index 6a376f1ef..89a003511 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/ValidationEngine.java @@ -761,8 +761,9 @@ public class ValidationEngine implements IValidatorResourceFetcher { System.out.print("* load file: "+fn); } System.out.println(" - ignored due to error: "+(e.getMessage() == null ? " (null - NPE)" : e.getMessage())); - if (debug) + if (debug || ((e.getMessage() != null && e.getMessage().contains("cannot be cast")))) { e.printStackTrace(); + } } return r; } From 977026e62e61ebff8bfb081236dbcf5648543450 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:44:54 +1100 Subject: [PATCH 28/44] Improve error message when profile generation fails --- .../java/org/hl7/fhir/r5/validation/InstanceValidator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 5accd1aef..f7205b412 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -3289,14 +3289,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat expression.append(" and " + discriminator + " is " + type); } else if (s.getType() == DiscriminatorType.PROFILE) { if (criteriaElement.getType().size() == 0) { - throw new DefinitionException("Profile based discriminators must have a type ("+criteriaElement.getId()+")"); + throw new DefinitionException("Profile based discriminators must have a type ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")"); } if (criteriaElement.getType().size() != 1) { - throw new DefinitionException("Profile based discriminators must have only one type ("+criteriaElement.getId()+")"); + throw new DefinitionException("Profile based discriminators must have only one type ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")"); } List list = discriminator.endsWith(".resolve()") || discriminator.equals("resolve()") ? criteriaElement.getType().get(0).getTargetProfile() : criteriaElement.getType().get(0).getProfile(); if (list.size() == 0) { - throw new DefinitionException("Profile based discriminators must have a type with a profile ("+criteriaElement.getId()+")"); + throw new DefinitionException("Profile based discriminators must have a type with a profile ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")"); } else if (list.size() > 1) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" or "); for (CanonicalType c : list) { From 6ea5016da55723f775c0112b4bed0621f9f78c22 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:45:32 +1100 Subject: [PATCH 29/44] fix JsonUtils to handle null --- .../src/main/java/org/hl7/fhir/utilities/json/JSONUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JSONUtil.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JSONUtil.java index 346f319e6..301574ea7 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JSONUtil.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JSONUtil.java @@ -28,6 +28,7 @@ import java.util.Map.Entry; import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonNull; import com.google.gson.JsonObject; public class JSONUtil { @@ -73,7 +74,7 @@ public class JSONUtil { public static String str(JsonObject json, String name) { JsonElement e = json.get(name); - return e == null ? null : e.getAsString(); + return e == null || e instanceof JsonNull ? null : e.getAsString(); } public static String str(JsonObject json, String name1, String name2) { From 3ca01a96593e787c485cbaee6dd54ff2617069a5 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:53:01 +1100 Subject: [PATCH 30/44] allow for profiles iiwth no derivation in test cases --- .../java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java index 9699e7b83..9c1bfd7e1 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java @@ -473,7 +473,9 @@ public class SnapShotGenerationTests { pu.setNewSlicingProcessing(true); pu.setIds(test.included, false); StructureDefinition base = TestingUtilities.context().fetchResource(StructureDefinition.class, test.included.getBaseDefinition()); - pu.generateSnapshot(base, test.included, test.included.getUrl(), "http://test.org/profile", test.included.getName()); + if (base != null) { + pu.generateSnapshot(base, test.included, test.included.getUrl(), "http://test.org/profile", test.included.getName()); + } if (!TestingUtilities.context().hasResource(StructureDefinition.class, test.included.getUrl())) TestingUtilities.context().cacheResource(test.included); int ec = 0; From 582a2699a51b1f3aeaeae375cad76794f78e1d79 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 17:53:28 +1100 Subject: [PATCH 31/44] Add PackageServer Client and tests --- .../hl7/fhir/r5/test/PackageClientTests.java | 101 +++++++++++ .../fhir/utilities/cache/PackageClient.java | 165 ++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java create mode 100644 org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java new file mode 100644 index 000000000..8c1e3b0a5 --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java @@ -0,0 +1,101 @@ +package org.hl7.fhir.r5.test; + +import java.io.IOException; +import java.util.List; + +import org.hl7.fhir.utilities.cache.PackageClient; +import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo; +import org.junit.Assert; +import org.junit.Test; + +public class PackageClientTests { + + @Test + public void testExists() throws IOException { + PackageClient client = new PackageClient("http://packages.fhir.org"); + Assert.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1")); + Assert.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2")); + Assert.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1")); + } + + @Test + public void testSearch() throws IOException { + PackageClient client = new PackageClient("http://packages.fhir.org"); + List matches = client.search("core", null, null, false); + for (PackageInfo pi : matches) { + System.out.println(pi.toString()); + } + Assert.assertTrue(matches.size() > 0); + } + + + @Test + public void testSearchNoMatches() throws IOException { + PackageClient client = new PackageClient("http://packages.fhir.org"); + List matches = client.search("corezxxx", null, null, false); + Assert.assertTrue(matches.size() == 0); + } + + @Test + public void testVersions() throws IOException { + PackageClient client = new PackageClient("http://packages.fhir.org"); + List matches = client.getVersions("Simplifier.Core.STU3"); + for (PackageInfo pi : matches) { + System.out.println(pi.toString()); + } + Assert.assertTrue(matches.size() > 0); + } + + @Test + public void testVersionsNone() throws IOException { + PackageClient client = new PackageClient("http://packages.fhir.org"); + List matches = client.getVersions("Simplifier.Core.STU3X"); + Assert.assertTrue(matches.size() == 0); + } + + + @Test + public void testExists2() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + Assert.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1")); + Assert.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2")); + Assert.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1")); + } + + @Test + public void testSearch2() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + List matches = client.search("core", null, null, false); + for (PackageInfo pi : matches) { + System.out.println(pi.toString()); + } + Assert.assertTrue(matches.size() > 0); + } + + + @Test + public void testSearchNoMatches2() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + List matches = client.search("corezxxx", null, null, false); + Assert.assertTrue(matches.size() == 0); + } + + @Test + public void testVersions2() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + List matches = client.getVersions("Simplifier.Core.STU3"); + for (PackageInfo pi : matches) { + System.out.println(pi.toString()); + } + Assert.assertTrue(matches.size() > 0); + } + + @Test + public void testVersionsNone2() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + List matches = client.getVersions("Simplifier.Core.STU3X"); + Assert.assertTrue(matches.size() == 0); + } + + +} diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java new file mode 100644 index 000000000..47b7b023c --- /dev/null +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java @@ -0,0 +1,165 @@ +package org.hl7.fhir.utilities.cache; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo; +import org.hl7.fhir.utilities.json.JSONUtil; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class PackageClient { + + public class PackageInfo { + private String id; + private String version; + private String fhirVersion; + private String description; + private String url; + public PackageInfo(String id, String version, String fhirVersion, String description, String url) { + super(); + this.id = id; + this.version = version; + this.fhirVersion = fhirVersion; + this.description = description; + this.url = url; + } + public String getId() { + return id; + } + public String getVersion() { + return version; + } + public String getFhirVersion() { + return fhirVersion; + } + public String getDescription() { + return description; + } + public String getUrl() { + return url; + } + @Override + public String toString() { + return id+"#"+(version == null ? "??" : version)+(fhirVersion == null ? "": "for FHIR "+fhirVersion)+(url == null ? "" : " @"+url)+(description == null ? "" : " '"+description+"'"); + } + + } + + private String address; + + + public PackageClient(String address) { + super(); + this.address = address; + } + + public boolean exists(String id, String ver) throws IOException { + List vl = getVersions(id); + for (PackageInfo pi : vl) { + if (ver.equals(pi.getVersion())) { + return true; + } + } + return false; + } + + public InputStream fetch(String id, String ver) throws IOException { + return fetchUrl(Utilities.pathURL(address, id, ver)); + } + + public InputStream fetch(PackageInfo info) throws IOException { + return fetchUrl(Utilities.pathURL(address, info.getId(), info.getVersion())); + } + + public InputStream fetchNpm(String id, String ver) throws IOException { + return fetchUrl(Utilities.pathURL(address, id, "-", id+"-"+ver+".tgz")); + } + + public List getVersions(String id) throws IOException { + List res = new ArrayList<>(); + JsonObject json; + try { + json = fetchJson(Utilities.pathURL(address, id)); + JsonObject versions = json.getAsJsonObject("versions"); + if (versions != null) { + for (String v : sorted(versions.keySet())) { + JsonObject obj = versions.getAsJsonObject(v); + res.add(new PackageInfo(JSONUtil.str(obj, "name"), JSONUtil.str(obj, "version"), JSONUtil.str(obj, "FhirVersion"), JSONUtil.str(obj, "description"), JSONUtil.str(obj, "url"))); + } + } + } catch (FileNotFoundException e) { + } + return res; + } + + private List sorted(Set keys) { + List res = new ArrayList<>(); + res.addAll(keys); + Collections.sort(res); + return res; + } + + public List search(String name, String canonical, String fhirVersion, boolean preRelease) throws IOException { + CommaSeparatedStringBuilder params = new CommaSeparatedStringBuilder("&"); + if (!Utilities.noString(name)) { + params.append("name="+name); + } + if (!Utilities.noString(canonical)) { + params.append("canonical="+canonical); + } + if (!Utilities.noString(fhirVersion)) { + params.append("fhirversion="+fhirVersion); + } + if (preRelease) { + params.append("prerelease="+preRelease); + } + List res = new ArrayList<>(); + try { + JsonArray json = fetchJsonArray(Utilities.pathURL(address, "catalog?")+params.toString()); + for (JsonElement e : json) { + JsonObject obj = (JsonObject) e; + res.add(new PackageInfo(JSONUtil.str(obj, "Name"), null, JSONUtil.str(obj, "FhirVersion"), JSONUtil.str(obj, "Description"), null)); + } + } catch (FileNotFoundException e1) { + } + return res; + } + + public Date getNewPackages(Date lastCalled, List updates) { + return null; + } + + private InputStream fetchUrl(String source) throws IOException { + URL url = new URL(source); + URLConnection c = url.openConnection(); + return c.getInputStream(); + } + + private JsonObject fetchJson(String source) throws IOException { + String src = TextFile.streamToString(fetchUrl(source)); + //System.out.println(src); + return (JsonObject) new com.google.gson.JsonParser().parse(src); + } + + private JsonArray fetchJsonArray(String source) throws IOException { + String src = TextFile.streamToString(fetchUrl(source)); + //System.out.println(src); + return (JsonArray) new com.google.gson.JsonParser().parse(src); + } + + +} From 9b562f3489d3250076d1eeaf1e89ed9857169158 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 18:02:36 +1100 Subject: [PATCH 32/44] more bug fixes in R3/R5 conversions --- .../convertors/VersionConvertor_30_50.java | 26 ++++++++++++++++++- .../convertors/conv30_50/ValueSet30_50.java | 4 +-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java index 7f6693c8c..9a3395139 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java @@ -154,8 +154,32 @@ public class VersionConvertor_30_50 { return tgt; } + public static org.hl7.fhir.r5.model.CodeType convertStringToCode(org.hl7.fhir.dstu3.model.StringType src) throws FHIRException { + org.hl7.fhir.r5.model.CodeType tgt = new org.hl7.fhir.r5.model.CodeType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + + public static org.hl7.fhir.dstu3.model.StringType convertCodeToString(org.hl7.fhir.r5.model.CodeType src) throws FHIRException { + org.hl7.fhir.dstu3.model.StringType tgt = new org.hl7.fhir.dstu3.model.StringType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + + public static org.hl7.fhir.dstu3.model.CodeType convertStringToCode(org.hl7.fhir.r5.model.StringType src) throws FHIRException { + org.hl7.fhir.dstu3.model.CodeType tgt = new org.hl7.fhir.dstu3.model.CodeType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + + public static org.hl7.fhir.r5.model.StringType convertCodeToString(org.hl7.fhir.dstu3.model.CodeType src) throws FHIRException { + org.hl7.fhir.r5.model.StringType tgt = new org.hl7.fhir.r5.model.StringType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + public static org.hl7.fhir.r5.model.DateType convertDate(org.hl7.fhir.dstu3.model.DateType src) throws FHIRException { - org.hl7.fhir.r5.model.DateType tgt = new org.hl7.fhir.r5.model.DateType(src.getValueAsString()); + org.hl7.fhir.r5.model.DateType tgt = new org.hl7.fhir.r5.model.DateType(src.getValueAsString()); copyElement(src, tgt); return tgt; } diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/ValueSet30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/ValueSet30_50.java index 426e77c80..00e2ea731 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/ValueSet30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/ValueSet30_50.java @@ -117,7 +117,7 @@ public class ValueSet30_50 { if (src.hasOp()) tgt.setOp(convertFilterOperator2(src.getOp())); if (src.hasValueElement()) - tgt.setValueElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getValueElement())); + tgt.setValueElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertStringToCode(src.getValueElement())); return tgt; } @@ -131,7 +131,7 @@ public class ValueSet30_50 { if (src.hasOp()) tgt.setOp(VersionConvertor_30_50.convertFilterOperator(src.getOp())); if (src.hasValueElement()) - tgt.setValueElement((org.hl7.fhir.r5.model.StringType) VersionConvertor_30_50.convertType(src.getValueElement())); + tgt.setValueElement((org.hl7.fhir.r5.model.StringType) VersionConvertor_30_50.convertCodeToString(src.getValueElement())); return tgt; } From 4d99bcb0c63dd0b16c84373dc8fd782546514c5d Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 18:07:21 +1100 Subject: [PATCH 33/44] better handling of circular dependencies in snap shot generator --- .../fhir/r5/conformance/ProfileUtilities.java | 16 ++++++++++++++-- .../org/hl7/fhir/r5/context/IWorkerContext.java | 3 ++- .../hl7/fhir/r5/context/SimpleWorkerContext.java | 6 ++++++ .../org/hl7/fhir/r5/test/PackageClientTests.java | 10 ++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 130946780..c80cc3877 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -463,6 +463,9 @@ public class ProfileUtilities extends TranslatingUtilities { if (derived == null) { throw new DefinitionException("no derived structure provided"); } + checkNotGenerating(base, "Base for generating a snapshot for the profile "+derived.getUrl()); + checkNotGenerating(derived, "Focus for generating a snapshot"); + derived.setUserData("profileutils.snapshot.generating", true); if (!base.hasType()) { throw new DefinitionException("Base profile "+base.getUrl()+" has no type"); @@ -622,6 +625,7 @@ public class ProfileUtilities extends TranslatingUtilities { derived.setSnapshot(null); throw e; } + derived.clearUserData("profileutils.snapshot.generating"); } private void checkDifferential(List elements, String type, String url) { @@ -853,10 +857,12 @@ public class ProfileUtilities extends TranslatingUtilities { CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue()); if (sd != null) { + checkNotGenerating(sd, "an extension definition"); if (!sd.hasSnapshot()) { StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); if (sdb == null) throw new DefinitionException("Unable to find base "+sd.getBaseDefinition()+" for "+sd.getUrl()); + checkNotGenerating(sdb, "an extension base"); generateSnapshot(sdb, sd, sd.getUrl(), (sdb.hasUserData("path")) ? Utilities.extractBaseUrl(sdb.getUserString("path")) : webUrl, sd.getName()); } ElementDefinition src; @@ -1424,7 +1430,7 @@ public class ProfileUtilities extends TranslatingUtilities { outcome.setSlicing(null); if (!outcome.getPath().startsWith(resultPathBase)) throw new DefinitionException("Adding wrong path"); - if (diffpos < diffMatches.size() && diffMatches.get(diffpos).getSliceName().equals(outcome.getSliceName())) { + if (diffpos < diffMatches.size() && diffMatches.get(diffpos).hasSliceName() && diffMatches.get(diffpos).getSliceName().equals(outcome.getSliceName())) { // if there's a diff, we update the outcome with diff // no? updateFromDefinition(outcome, diffMatches.get(diffpos), profileName, closed, url); //then process any children @@ -1540,6 +1546,12 @@ public class ProfileUtilities extends TranslatingUtilities { } + private void checkNotGenerating(StructureDefinition sd, String role) { + if (sd.hasUserData("profileutils.snapshot.generating")) { + throw new FHIRException("Attempt to use a snapshot on profile '"+sd.getUrl()+"' as "+role+" before it is generated"); + } + } + private boolean isBaseResource(List types) { if (types.isEmpty()) return false; @@ -2566,7 +2578,7 @@ public class ProfileUtilities extends TranslatingUtilities { String url = u.getValue(); boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url); while (url != null && !tgtOk) { - StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); + StructureDefinition sd = context.fetchRawProfile(url); if (sd == null) { if (messages != null) { messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index 19d69ca45..11c4a94cf 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -539,7 +539,8 @@ public interface IWorkerContext { public void setOverrideVersionNs(String value); public StructureDefinition fetchTypeDefinition(String typeName); - + public StructureDefinition fetchRawProfile(String url); + public void setUcumService(UcumService ucumService); public String getLinkForUrl(String corePath, String s); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index a5838a0e4..455dc659f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -640,6 +640,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon return r; } + @Override + public StructureDefinition fetchRawProfile(String uri) { + StructureDefinition r = super.fetchResource(StructureDefinition.class, uri); + return r; + } + @Override public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException { generateSnapshot(p, false); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java index 8c1e3b0a5..6376b2425 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java @@ -87,6 +87,16 @@ public class PackageClientTests { for (PackageInfo pi : matches) { System.out.println(pi.toString()); } + Assert.assertTrue(matches.size() == 0); + } + + @Test + public void testVersions2A() throws IOException { + PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + List matches = client.getVersions("hl7.fhir.us.core"); + for (PackageInfo pi : matches) { + System.out.println(pi.toString()); + } Assert.assertTrue(matches.size() > 0); } From fccd3c1871ac3b0c555cd178d38e2a2eca029bd9 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 12 Feb 2020 20:24:09 +1100 Subject: [PATCH 34/44] test for existence of both lang and xml:lang on the xhtml div --- .../hl7/fhir/r5/test/PackageClientTests.java | 1 - .../fhir/r5/validation/InstanceValidator.java | 20 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java index 6376b2425..fed14f812 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java @@ -71,7 +71,6 @@ public class PackageClientTests { } Assert.assertTrue(matches.size() > 0); } - @Test public void testSearchNoMatches2() throws IOException { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index f7205b412..649f46187 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -3716,11 +3716,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat Element div = text.getNamedChild("div"); if (lang != null && div != null) { XhtmlNode xhtml = div.getXhtml(); - String xl = xhtml.getAttribute("lang"); - if (xl == null) { - warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have a language tag"); - } else if (!xl.equals(lang)) { - warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has a language ("+xl+"), but they differ "); + String l = xhtml.getAttribute("lang"); + String xl = xhtml.getAttribute("xml:lang"); + if (l == null && xl == null) { + warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have an lang or an xml:lang tag (needs both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)"); + } else { + if (l == null) { + warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have a lang tag (needs both lang and xml:lang - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)"); + } else if (!l.equals(lang)) { + warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has a lang ("+l+"), but they differ "); + } + if (xl == null) { + warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have an xml:lang tag (needs both lang and xml:lang - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)"); + } else if (!xl.equals(lang)) { + warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has an xml:lang ("+xl+"), but they differ "); + } } } } From 91e475a1a1f3836db7ecfbd6fec164fab290aab8 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 10:13:35 +1100 Subject: [PATCH 35/44] fix Questionnaire EnableWhen validation + fix up tests for public package server --- .../hl7/fhir/r5/test/PackageClientTests.java | 12 +++--- .../fhir/r5/validation/InstanceValidator.java | 41 +++++++++++-------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java index fed14f812..807d424e2 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java @@ -56,7 +56,7 @@ public class PackageClientTests { @Test public void testExists2() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); Assert.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1")); Assert.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2")); Assert.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1")); @@ -64,7 +64,7 @@ public class PackageClientTests { @Test public void testSearch2() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); List matches = client.search("core", null, null, false); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -74,14 +74,14 @@ public class PackageClientTests { @Test public void testSearchNoMatches2() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); List matches = client.search("corezxxx", null, null, false); Assert.assertTrue(matches.size() == 0); } @Test public void testVersions2() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); List matches = client.getVersions("Simplifier.Core.STU3"); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -91,7 +91,7 @@ public class PackageClientTests { @Test public void testVersions2A() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); List matches = client.getVersions("hl7.fhir.us.core"); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -101,7 +101,7 @@ public class PackageClientTests { @Test public void testVersionsNone2() throws IOException { - PackageClient client = new PackageClient("http://local.fhir.org:960/packages"); + PackageClient client = new PackageClient("http://test.fhir.org/packages"); List matches = client.getVersions("Simplifier.Core.STU3X"); Assert.assertTrue(matches.size() == 0); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 649f46187..efdcd6c6c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -3602,7 +3602,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } else if (element.getType().equals("Observation")) { validateObservation(errors, element, stack); } else if (element.getType().equals("Questionnaire")) { - validateQuestionannaire(errors, element, stack); + ArrayList parents = new ArrayList<>(); + parents.add(element); + validateQuestionannaireItem(errors, element, element, stack, parents); } else if (element.getType().equals("QuestionnaireResponse")) { validateQuestionannaireResponse(hostContext, errors, element, stack); } else if (element.getType().equals("CapabilityStatement")) { @@ -3621,32 +3623,35 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return res; } - private void validateQuestionannaire(List errors, Element element, NodeStack stack) { + private void validateQuestionannaireItem(List errors, Element element, Element questionnaire, NodeStack stack, List parents) { List list = getItems(element); for (int i = 0; i < list.size(); i++) { Element e = list.get(i); - NodeStack ns = stack.push(element, i, e.getProperty().getDefinition(), e.getProperty().getDefinition()); - validateQuestionnaireElement(errors, ns, element, e, new ArrayList<>()); + NodeStack ns = stack.push(e, i, e.getProperty().getDefinition(), e.getProperty().getDefinition()); + validateQuestionnaireElement(errors, ns, questionnaire, e, parents); + validateQuestionannaireItem(errors, e, questionnaire, ns, list); } - } private void validateQuestionnaireElement(List errors, NodeStack ns, Element questionnaire, Element item, List parents) { // R4+ if (FHIRVersion.isR4Plus(context.getVersion())) { - if (item.hasChild("enableWhen")) { - Element ew = item.getNamedChild("enableWhen"); - String ql = ew.getNamedChildValue("question"); - if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, ql != null, "Questions with an enableWhen must have a value for the question link")) { - Element tgt = getQuestionById(item, ql); - if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt == null, "Questions with an enableWhen cannot refer to an inner question for it's enableWhen condition")) { - tgt = getQuestionById(questionnaire, ql); - if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != null, "Unable to find "+ql+" target for this question enableWhen")) { - if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != item, "Target for this question enableWhen can't reference itself")) { - warning(errors, IssueType.BUSINESSRULE, ns.literalPath, isBefore(item, tgt, parents), "The target of this enableWhen rule ("+ql+") comes after the question itself"); + if (item.hasChildren("enableWhen")) { + List ewl = item.getChildren("enableWhen"); + for (Element ew : ewl) { +// Element ew = item.getNamedChild("enableWhen"); + String ql = ew.getNamedChildValue("question"); + if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, ql != null, "Questions with an enableWhen must have a value for the question link")) { + Element tgt = getQuestionById(item, ql); + if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt == null, "Questions with an enableWhen cannot refer to an inner question for it's enableWhen condition")) { + tgt = getQuestionById(questionnaire, ql); + if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != null, "Unable to find target '"+ql+"' for this question enableWhen")) { + if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != item, "Target for this question enableWhen can't reference itself")) { + warning(errors, IssueType.BUSINESSRULE, ns.literalPath, isBefore(item, tgt, parents), "The target of this enableWhen rule ("+ql+") comes after the question itself"); + } } - } - } + } + } } } } @@ -3677,7 +3682,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat for (Element e : element.getChildren()) { if (e == descendant) return true; - if (isChild(element, descendant)) + if (isChild(e, descendant)) return true; } return false; From 52bc73a56183f5a1397c2fa1d4f55e11fe52daa3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 12:08:05 +1100 Subject: [PATCH 36/44] more fixes for Questionnaire validation --- .../hl7/fhir/r5/validation/InstanceValidator.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index efdcd6c6c..d23f65a01 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -3629,7 +3629,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat Element e = list.get(i); NodeStack ns = stack.push(e, i, e.getProperty().getDefinition(), e.getProperty().getDefinition()); validateQuestionnaireElement(errors, ns, questionnaire, e, parents); - validateQuestionannaireItem(errors, e, questionnaire, ns, list); + List np = new ArrayList(); + np.add(e); + np.addAll(parents); + validateQuestionannaireItem(errors, e, questionnaire, ns, np); } } @@ -3647,7 +3650,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat tgt = getQuestionById(questionnaire, ql); if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != null, "Unable to find target '"+ql+"' for this question enableWhen")) { if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != item, "Target for this question enableWhen can't reference itself")) { - warning(errors, IssueType.BUSINESSRULE, ns.literalPath, isBefore(item, tgt, parents), "The target of this enableWhen rule ("+ql+") comes after the question itself"); + if (!isBefore(item, tgt, parents)) { + warning(errors, IssueType.BUSINESSRULE, ns.literalPath, false, "The target of this enableWhen rule ("+ql+") comes after the question itself"); + } } } } @@ -3659,6 +3664,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private boolean isBefore(Element item, Element tgt, List parents) { // we work up the list, looking for tgt in the children of the parents + if (parents.contains(tgt)) { + // actually, if the target is a parent, that's automatically ok + return true; + } for (Element p : parents) { int i = findIndex(p, item); int t = findIndex(p, tgt); From bc1f87e29f93216439f4fa5920aee4e35e310dbc Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 12:26:15 +1100 Subject: [PATCH 37/44] Release new version 4.1.62 --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 4 ++-- release.bat | 4 ++-- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 54bfb1e60..c1e63c036 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index e1e64e41c..529b24eee 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 698148ecc..903d562d8 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 6fab60a00..ee11d9a4d 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 4a8780c47..7d660914f 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index fd5b7344f..e76dde00e 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 8edfda25a..12e7367f8 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 4b09629e3..d94fc7238 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index c3dde4566..2a5d1b378 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 24c7b00bd..8690acbcd 100644 --- a/pom.xml +++ b/pom.xml @@ -13,11 +13,11 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.61-SNAPSHOT + 4.1.62-SNAPSHOT 4.1.0 - 1.0.41-SNAPSHOT + 1.0.42-SNAPSHOT org.hl7.fhir.core diff --git a/release.bat b/release.bat index c322309bc..8edc066df 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.60 -set newver=4.1.61 +set oldver=4.1.61 +set newver=4.1.62 echo .. echo ===================================================================== From 490aef6f9b499f4bfb9a71f55425ffc4063ae45d Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 12 Feb 2020 20:39:37 -0500 Subject: [PATCH 38/44] fixed Meta.getSecurity(String,String) bug --- .../java/org/hl7/fhir/dstu2/model/Meta.java | 2 +- .../org/hl7/fhir/dstu2/test/MetaTest.java | 24 + .../java/org/hl7/fhir/dstu3/model/Meta.java | 2 +- .../org/hl7/fhir/dstu3/test/MetaTest.java | 26 + .../main/java/org/hl7/fhir/r4/model/Meta.java | 2 +- .../java/org/hl7/fhir/r4/test/MetaTest.java | 26 + .../main/java/org/hl7/fhir/r5/model/Meta.java | 1370 ++++++++--------- .../java/org/hl7/fhir/r5/test/MetaTest.java | 26 + 8 files changed, 790 insertions(+), 688 deletions(-) create mode 100644 org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/test/MetaTest.java create mode 100644 org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/test/MetaTest.java create mode 100644 org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/MetaTest.java create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/MetaTest.java diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Meta.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Meta.java index bb0d97b8f..ae2b373e1 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Meta.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Meta.java @@ -277,7 +277,7 @@ public class Meta extends Type implements IBaseMetaType { * null if none */ public Coding getSecurity(String theSystem, String theCode) { - for (Coding next : getTag()) { + for (Coding next : getSecurity()) { if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { return next; } diff --git a/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/test/MetaTest.java b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/test/MetaTest.java new file mode 100644 index 000000000..6ded2d99c --- /dev/null +++ b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/test/MetaTest.java @@ -0,0 +1,24 @@ +package org.hl7.fhir.dstu2.test; + +import org.hl7.fhir.dstu2.model.Coding; +import org.hl7.fhir.dstu2.model.Meta; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class MetaTest { + public static String TEST_SYSTEM = "TEST_SYSTEM"; + public static String TEST_CODE = "TEST_CODE"; + + @Test + public void testMetaSecurity() { + Meta meta = new Meta(); + Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE); + assertTrue(meta.hasSecurity()); + assertNotNull(meta.getSecurity()); + assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(1, meta.getSecurity().size()); + assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + } +} diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Meta.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Meta.java index e98bef91f..90bfbf7fa 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Meta.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Meta.java @@ -421,7 +421,7 @@ public class Meta extends Type implements IBaseMetaType { * null if none */ public Coding getSecurity(String theSystem, String theCode) { - for (Coding next : getTag()) { + for (Coding next : getSecurity()) { if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { return next; } diff --git a/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/test/MetaTest.java b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/test/MetaTest.java new file mode 100644 index 000000000..2b6157fcc --- /dev/null +++ b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/test/MetaTest.java @@ -0,0 +1,26 @@ +package org.hl7.fhir.dstu3.test; + +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.Meta; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class MetaTest { + public static String TEST_SYSTEM = "TEST_SYSTEM"; + public static String TEST_CODE = "TEST_CODE"; + + @Test + public void testMetaSecurity() { + Meta meta = new Meta(); + Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE); + assertTrue(meta.hasSecurity()); + assertNotNull(meta.getSecurity()); + assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(1, meta.getSecurity().size()); + assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + } +} + diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Meta.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Meta.java index cf6835922..5a6440428 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Meta.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Meta.java @@ -476,7 +476,7 @@ public class Meta extends Type implements IBaseMetaType { * null if none */ public Coding getSecurity(String theSystem, String theCode) { - for (Coding next : getTag()) { + for (Coding next : getSecurity()) { if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { return next; } diff --git a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/MetaTest.java b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/MetaTest.java new file mode 100644 index 000000000..215ab9f7e --- /dev/null +++ b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/MetaTest.java @@ -0,0 +1,26 @@ +package org.hl7.fhir.r4.test; + +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Meta; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +public class MetaTest { + public static String TEST_SYSTEM = "TEST_SYSTEM"; + public static String TEST_CODE = "TEST_CODE"; + + @Test + public void testMetaSecurity() { + Meta meta = new Meta(); + Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE); + assertTrue(meta.hasSecurity()); + assertNotNull(meta.getSecurity()); + assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(1, meta.getSecurity().size()); + assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + } +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Meta.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Meta.java index d6030976d..49fe64350 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Meta.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Meta.java @@ -1,685 +1,685 @@ -package org.hl7.fhir.r5.model; - - -/* - * #%L - * org.hl7.fhir.r5 - * %% - * Copyright (C) 2014 - 2019 Health Level 7 - * %% - * Licensed under the Apache License, Version 2.0 (the \"License\"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an \"AS IS\" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -/* - Copyright (c) 2011+, HL7, Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, \ - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this \ - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, \ - this list of conditions and the following disclaimer in the documentation \ - and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND \ - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \ - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \ - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \ - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \ - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR \ - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \ - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \ - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \ - POSSIBILITY OF SUCH DAMAGE. - */ - -// Generated on Tue, Dec 31, 2019 12:12+1100 for FHIR vcurrent - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.r5.model.Enumerations.*; -import org.hl7.fhir.instance.model.api.IBaseDatatypeElement; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.instance.model.api.ICompositeType; -import ca.uhn.fhir.model.api.annotation.Child; -import ca.uhn.fhir.model.api.annotation.ChildOrder; -import ca.uhn.fhir.model.api.annotation.DatatypeDef; -import ca.uhn.fhir.model.api.annotation.Description; -import ca.uhn.fhir.model.api.annotation.Block; - -import org.hl7.fhir.instance.model.api.IBaseMetaType; -/** - * Base StructureDefinition for Meta Type: The metadata about a resource. This is content in the resource that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource. - */ -@DatatypeDef(name="Meta") -public class Meta extends DataType implements IBaseMetaType { - - /** - * The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. - */ - @Child(name = "versionId", type = {IdType.class}, order=0, min=0, max=1, modifier=false, summary=true) - @Description(shortDefinition="Version specific identifier", formalDefinition="The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted." ) - protected IdType versionId; - - /** - * When the resource last changed - e.g. when the version changed. - */ - @Child(name = "lastUpdated", type = {InstantType.class}, order=1, min=0, max=1, modifier=false, summary=true) - @Description(shortDefinition="When the resource version last changed", formalDefinition="When the resource last changed - e.g. when the version changed." ) - protected InstantType lastUpdated; - - /** - * A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. - */ - @Child(name = "source", type = {UriType.class}, order=2, min=0, max=1, modifier=false, summary=true) - @Description(shortDefinition="Identifies where the resource comes from", formalDefinition="A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc." ) - protected UriType source; - - /** - * A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url). - */ - @Child(name = "profile", type = {CanonicalType.class}, order=3, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) - @Description(shortDefinition="Profiles this resource claims to conform to", formalDefinition="A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url)." ) - protected List profile; - - /** - * Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure. - */ - @Child(name = "security", type = {Coding.class}, order=4, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) - @Description(shortDefinition="Security Labels applied to this resource", formalDefinition="Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure." ) - @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/security-labels") - protected List security; - - /** - * Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource. - */ - @Child(name = "tag", type = {Coding.class}, order=5, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) - @Description(shortDefinition="Tags applied to this resource", formalDefinition="Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource." ) - @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/common-tags") - protected List tag; - - private static final long serialVersionUID = -1386695622L; - - /** - * Constructor - */ - public Meta() { - super(); - } - - /** - * @return {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value - */ - public IdType getVersionIdElement() { - if (this.versionId == null) - if (Configuration.errorOnAutoCreate()) - throw new Error("Attempt to auto-create Meta.versionId"); - else if (Configuration.doAutoCreate()) - this.versionId = new IdType(); // bb - return this.versionId; - } - - public boolean hasVersionIdElement() { - return this.versionId != null && !this.versionId.isEmpty(); - } - - public boolean hasVersionId() { - return this.versionId != null && !this.versionId.isEmpty(); - } - - /** - * @param value {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value - */ - public Meta setVersionIdElement(IdType value) { - this.versionId = value; - return this; - } - - /** - * @return The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. - */ - public String getVersionId() { - return this.versionId == null ? null : this.versionId.getValue(); - } - - /** - * @param value The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. - */ - public Meta setVersionId(String value) { - if (Utilities.noString(value)) - this.versionId = null; - else { - if (this.versionId == null) - this.versionId = new IdType(); - this.versionId.setValue(value); - } - return this; - } - - /** - * @return {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value - */ - public InstantType getLastUpdatedElement() { - if (this.lastUpdated == null) - if (Configuration.errorOnAutoCreate()) - throw new Error("Attempt to auto-create Meta.lastUpdated"); - else if (Configuration.doAutoCreate()) - this.lastUpdated = new InstantType(); // bb - return this.lastUpdated; - } - - public boolean hasLastUpdatedElement() { - return this.lastUpdated != null && !this.lastUpdated.isEmpty(); - } - - public boolean hasLastUpdated() { - return this.lastUpdated != null && !this.lastUpdated.isEmpty(); - } - - /** - * @param value {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value - */ - public Meta setLastUpdatedElement(InstantType value) { - this.lastUpdated = value; - return this; - } - - /** - * @return When the resource last changed - e.g. when the version changed. - */ - public Date getLastUpdated() { - return this.lastUpdated == null ? null : this.lastUpdated.getValue(); - } - - /** - * @param value When the resource last changed - e.g. when the version changed. - */ - public Meta setLastUpdated(Date value) { - if (value == null) - this.lastUpdated = null; - else { - if (this.lastUpdated == null) - this.lastUpdated = new InstantType(); - this.lastUpdated.setValue(value); - } - return this; - } - - /** - * @return {@link #source} (A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.). This is the underlying object with id, value and extensions. The accessor "getSource" gives direct access to the value - */ - public UriType getSourceElement() { - if (this.source == null) - if (Configuration.errorOnAutoCreate()) - throw new Error("Attempt to auto-create Meta.source"); - else if (Configuration.doAutoCreate()) - this.source = new UriType(); // bb - return this.source; - } - - public boolean hasSourceElement() { - return this.source != null && !this.source.isEmpty(); - } - - public boolean hasSource() { - return this.source != null && !this.source.isEmpty(); - } - - /** - * @param value {@link #source} (A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.). This is the underlying object with id, value and extensions. The accessor "getSource" gives direct access to the value - */ - public Meta setSourceElement(UriType value) { - this.source = value; - return this; - } - - /** - * @return A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. - */ - public String getSource() { - return this.source == null ? null : this.source.getValue(); - } - - /** - * @param value A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. - */ - public Meta setSource(String value) { - if (Utilities.noString(value)) - this.source = null; - else { - if (this.source == null) - this.source = new UriType(); - this.source.setValue(value); - } - return this; - } - - /** - * @return {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) - */ - public List getProfile() { - if (this.profile == null) - this.profile = new ArrayList(); - return this.profile; - } - - /** - * @return Returns a reference to this for easy method chaining - */ - public Meta setProfile(List theProfile) { - this.profile = theProfile; - return this; - } - - public boolean hasProfile() { - if (this.profile == null) - return false; - for (CanonicalType item : this.profile) - if (!item.isEmpty()) - return true; - return false; - } - - /** - * @return {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) - */ - public CanonicalType addProfileElement() {//2 - CanonicalType t = new CanonicalType(); - if (this.profile == null) - this.profile = new ArrayList(); - this.profile.add(t); - return t; - } - - /** - * @param value {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) - */ - public Meta addProfile(String value) { //1 - CanonicalType t = new CanonicalType(); - t.setValue(value); - if (this.profile == null) - this.profile = new ArrayList(); - this.profile.add(t); - return this; - } - - /** - * @param value {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) - */ - public boolean hasProfile(String value) { - if (this.profile == null) - return false; - for (CanonicalType v : this.profile) - if (v.getValue().equals(value)) // canonical - return true; - return false; - } - - /** - * @return {@link #security} (Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.) - */ - public List getSecurity() { - if (this.security == null) - this.security = new ArrayList(); - return this.security; - } - - /** - * @return Returns a reference to this for easy method chaining - */ - public Meta setSecurity(List theSecurity) { - this.security = theSecurity; - return this; - } - - public boolean hasSecurity() { - if (this.security == null) - return false; - for (Coding item : this.security) - if (!item.isEmpty()) - return true; - return false; - } - - public Coding addSecurity() { //3 - Coding t = new Coding(); - if (this.security == null) - this.security = new ArrayList(); - this.security.add(t); - return t; - } - - public Meta addSecurity(Coding t) { //3 - if (t == null) - return this; - if (this.security == null) - this.security = new ArrayList(); - this.security.add(t); - return this; - } - - /** - * @return The first repetition of repeating field {@link #security}, creating it if it does not already exist {3} - */ - public Coding getSecurityFirstRep() { - if (getSecurity().isEmpty()) { - addSecurity(); - } - return getSecurity().get(0); - } - - /** - * @return {@link #tag} (Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.) - */ - public List getTag() { - if (this.tag == null) - this.tag = new ArrayList(); - return this.tag; - } - - /** - * @return Returns a reference to this for easy method chaining - */ - public Meta setTag(List theTag) { - this.tag = theTag; - return this; - } - - public boolean hasTag() { - if (this.tag == null) - return false; - for (Coding item : this.tag) - if (!item.isEmpty()) - return true; - return false; - } - - public Coding addTag() { //3 - Coding t = new Coding(); - if (this.tag == null) - this.tag = new ArrayList(); - this.tag.add(t); - return t; - } - - public Meta addTag(Coding t) { //3 - if (t == null) - return this; - if (this.tag == null) - this.tag = new ArrayList(); - this.tag.add(t); - return this; - } - - /** - * @return The first repetition of repeating field {@link #tag}, creating it if it does not already exist {3} - */ - public Coding getTagFirstRep() { - if (getTag().isEmpty()) { - addTag(); - } - return getTag().get(0); - } - - protected void listChildren(List children) { - super.listChildren(children); - children.add(new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.", 0, 1, versionId)); - children.add(new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated)); - children.add(new Property("source", "uri", "A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.", 0, 1, source)); - children.add(new Property("profile", "canonical(StructureDefinition)", "A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).", 0, java.lang.Integer.MAX_VALUE, profile)); - children.add(new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security)); - children.add(new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag)); - } - - @Override - public Property getNamedProperty(int _hash, String _name, boolean _checkValid) throws FHIRException { - switch (_hash) { - case -1407102957: /*versionId*/ return new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.", 0, 1, versionId); - case 1649733957: /*lastUpdated*/ return new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated); - case -896505829: /*source*/ return new Property("source", "uri", "A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.", 0, 1, source); - case -309425751: /*profile*/ return new Property("profile", "canonical(StructureDefinition)", "A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).", 0, java.lang.Integer.MAX_VALUE, profile); - case 949122880: /*security*/ return new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security); - case 114586: /*tag*/ return new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag); - default: return super.getNamedProperty(_hash, _name, _checkValid); - } - - } - - @Override - public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException { - switch (hash) { - case -1407102957: /*versionId*/ return this.versionId == null ? new Base[0] : new Base[] {this.versionId}; // IdType - case 1649733957: /*lastUpdated*/ return this.lastUpdated == null ? new Base[0] : new Base[] {this.lastUpdated}; // InstantType - case -896505829: /*source*/ return this.source == null ? new Base[0] : new Base[] {this.source}; // UriType - case -309425751: /*profile*/ return this.profile == null ? new Base[0] : this.profile.toArray(new Base[this.profile.size()]); // CanonicalType - case 949122880: /*security*/ return this.security == null ? new Base[0] : this.security.toArray(new Base[this.security.size()]); // Coding - case 114586: /*tag*/ return this.tag == null ? new Base[0] : this.tag.toArray(new Base[this.tag.size()]); // Coding - default: return super.getProperty(hash, name, checkValid); - } - - } - - @Override - public Base setProperty(int hash, String name, Base value) throws FHIRException { - switch (hash) { - case -1407102957: // versionId - this.versionId = TypeConvertor.castToId(value); // IdType - return value; - case 1649733957: // lastUpdated - this.lastUpdated = TypeConvertor.castToInstant(value); // InstantType - return value; - case -896505829: // source - this.source = TypeConvertor.castToUri(value); // UriType - return value; - case -309425751: // profile - this.getProfile().add(TypeConvertor.castToCanonical(value)); // CanonicalType - return value; - case 949122880: // security - this.getSecurity().add(TypeConvertor.castToCoding(value)); // Coding - return value; - case 114586: // tag - this.getTag().add(TypeConvertor.castToCoding(value)); // Coding - return value; - default: return super.setProperty(hash, name, value); - } - - } - - @Override - public Base setProperty(String name, Base value) throws FHIRException { - if (name.equals("versionId")) { - this.versionId = TypeConvertor.castToId(value); // IdType - } else if (name.equals("lastUpdated")) { - this.lastUpdated = TypeConvertor.castToInstant(value); // InstantType - } else if (name.equals("source")) { - this.source = TypeConvertor.castToUri(value); // UriType - } else if (name.equals("profile")) { - this.getProfile().add(TypeConvertor.castToCanonical(value)); - } else if (name.equals("security")) { - this.getSecurity().add(TypeConvertor.castToCoding(value)); - } else if (name.equals("tag")) { - this.getTag().add(TypeConvertor.castToCoding(value)); - } else - return super.setProperty(name, value); - return value; - } - - @Override - public Base makeProperty(int hash, String name) throws FHIRException { - switch (hash) { - case -1407102957: return getVersionIdElement(); - case 1649733957: return getLastUpdatedElement(); - case -896505829: return getSourceElement(); - case -309425751: return addProfileElement(); - case 949122880: return addSecurity(); - case 114586: return addTag(); - default: return super.makeProperty(hash, name); - } - - } - - @Override - public String[] getTypesForProperty(int hash, String name) throws FHIRException { - switch (hash) { - case -1407102957: /*versionId*/ return new String[] {"id"}; - case 1649733957: /*lastUpdated*/ return new String[] {"instant"}; - case -896505829: /*source*/ return new String[] {"uri"}; - case -309425751: /*profile*/ return new String[] {"canonical"}; - case 949122880: /*security*/ return new String[] {"Coding"}; - case 114586: /*tag*/ return new String[] {"Coding"}; - default: return super.getTypesForProperty(hash, name); - } - - } - - @Override - public Base addChild(String name) throws FHIRException { - if (name.equals("versionId")) { - throw new FHIRException("Cannot call addChild on a primitive type Meta.versionId"); - } - else if (name.equals("lastUpdated")) { - throw new FHIRException("Cannot call addChild on a primitive type Meta.lastUpdated"); - } - else if (name.equals("source")) { - throw new FHIRException("Cannot call addChild on a primitive type Meta.source"); - } - else if (name.equals("profile")) { - throw new FHIRException("Cannot call addChild on a primitive type Meta.profile"); - } - else if (name.equals("security")) { - return addSecurity(); - } - else if (name.equals("tag")) { - return addTag(); - } - else - return super.addChild(name); - } - - public String fhirType() { - return "Meta"; - - } - - public Meta copy() { - Meta dst = new Meta(); - copyValues(dst); - return dst; - } - - public void copyValues(Meta dst) { - super.copyValues(dst); - dst.versionId = versionId == null ? null : versionId.copy(); - dst.lastUpdated = lastUpdated == null ? null : lastUpdated.copy(); - dst.source = source == null ? null : source.copy(); - if (profile != null) { - dst.profile = new ArrayList(); - for (CanonicalType i : profile) - dst.profile.add(i.copy()); - }; - if (security != null) { - dst.security = new ArrayList(); - for (Coding i : security) - dst.security.add(i.copy()); - }; - if (tag != null) { - dst.tag = new ArrayList(); - for (Coding i : tag) - dst.tag.add(i.copy()); - }; - } - - protected Meta typedCopy() { - return copy(); - } - - @Override - public boolean equalsDeep(Base other_) { - if (!super.equalsDeep(other_)) - return false; - if (!(other_ instanceof Meta)) - return false; - Meta o = (Meta) other_; - return compareDeep(versionId, o.versionId, true) && compareDeep(lastUpdated, o.lastUpdated, true) - && compareDeep(source, o.source, true) && compareDeep(profile, o.profile, true) && compareDeep(security, o.security, true) - && compareDeep(tag, o.tag, true); - } - - @Override - public boolean equalsShallow(Base other_) { - if (!super.equalsShallow(other_)) - return false; - if (!(other_ instanceof Meta)) - return false; - Meta o = (Meta) other_; - return compareValues(versionId, o.versionId, true) && compareValues(lastUpdated, o.lastUpdated, true) - && compareValues(source, o.source, true) && compareValues(profile, o.profile, true); - } - - public boolean isEmpty() { - return super.isEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty(versionId, lastUpdated, source - , profile, security, tag); - } - -// Manual code (from Configuration.txt)t: - /** - * Convenience method which adds a tag - * - * @param theSystem The code system - * @param theCode The code - * @param theDisplay The display name - * @return Returns a reference to this for easy chaining - */ - public Meta addTag(String theSystem, String theCode, String theDisplay) { - addTag().setSystem(theSystem).setCode(theCode).setDisplay(theDisplay); - return this; - } - - /** - * Returns the first tag (if any) that has the given system and code, or returns - * null if none - */ - public Coding getTag(String theSystem, String theCode) { - for (Coding next : getTag()) { - if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { - return next; - } - } - return null; - } - - /** - * Returns the first security label (if any) that has the given system and code, or returns - * null if none - */ - public Coding getSecurity(String theSystem, String theCode) { - for (Coding next : getTag()) { - if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { - return next; - } - } - return null; - } - -// end addition - -} - +package org.hl7.fhir.r5.model; + + +/* + * #%L + * org.hl7.fhir.r5 + * %% + * Copyright (C) 2014 - 2019 Health Level 7 + * %% + * Licensed under the Apache License, Version 2.0 (the \"License\"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an \"AS IS\" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +/* + Copyright (c) 2011+, HL7, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, \ + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this \ + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, \ + this list of conditions and the following disclaimer in the documentation \ + and/or other materials provided with the distribution. + * Neither the name of HL7 nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND \ + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \ + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \ + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \ + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT \ + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR \ + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \ + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \ + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \ + POSSIBILITY OF SUCH DAMAGE. + */ + +// Generated on Tue, Dec 31, 2019 12:12+1100 for FHIR vcurrent + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.r5.model.Enumerations.*; +import org.hl7.fhir.instance.model.api.IBaseDatatypeElement; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.instance.model.api.ICompositeType; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ChildOrder; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Block; + +import org.hl7.fhir.instance.model.api.IBaseMetaType; +/** + * Base StructureDefinition for Meta Type: The metadata about a resource. This is content in the resource that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource. + */ +@DatatypeDef(name="Meta") +public class Meta extends DataType implements IBaseMetaType { + + /** + * The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. + */ + @Child(name = "versionId", type = {IdType.class}, order=0, min=0, max=1, modifier=false, summary=true) + @Description(shortDefinition="Version specific identifier", formalDefinition="The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted." ) + protected IdType versionId; + + /** + * When the resource last changed - e.g. when the version changed. + */ + @Child(name = "lastUpdated", type = {InstantType.class}, order=1, min=0, max=1, modifier=false, summary=true) + @Description(shortDefinition="When the resource version last changed", formalDefinition="When the resource last changed - e.g. when the version changed." ) + protected InstantType lastUpdated; + + /** + * A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. + */ + @Child(name = "source", type = {UriType.class}, order=2, min=0, max=1, modifier=false, summary=true) + @Description(shortDefinition="Identifies where the resource comes from", formalDefinition="A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc." ) + protected UriType source; + + /** + * A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url). + */ + @Child(name = "profile", type = {CanonicalType.class}, order=3, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) + @Description(shortDefinition="Profiles this resource claims to conform to", formalDefinition="A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url)." ) + protected List profile; + + /** + * Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure. + */ + @Child(name = "security", type = {Coding.class}, order=4, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) + @Description(shortDefinition="Security Labels applied to this resource", formalDefinition="Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure." ) + @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/security-labels") + protected List security; + + /** + * Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource. + */ + @Child(name = "tag", type = {Coding.class}, order=5, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true) + @Description(shortDefinition="Tags applied to this resource", formalDefinition="Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource." ) + @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/common-tags") + protected List tag; + + private static final long serialVersionUID = -1386695622L; + + /** + * Constructor + */ + public Meta() { + super(); + } + + /** + * @return {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value + */ + public IdType getVersionIdElement() { + if (this.versionId == null) + if (Configuration.errorOnAutoCreate()) + throw new Error("Attempt to auto-create Meta.versionId"); + else if (Configuration.doAutoCreate()) + this.versionId = new IdType(); // bb + return this.versionId; + } + + public boolean hasVersionIdElement() { + return this.versionId != null && !this.versionId.isEmpty(); + } + + public boolean hasVersionId() { + return this.versionId != null && !this.versionId.isEmpty(); + } + + /** + * @param value {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value + */ + public Meta setVersionIdElement(IdType value) { + this.versionId = value; + return this; + } + + /** + * @return The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. + */ + public String getVersionId() { + return this.versionId == null ? null : this.versionId.getValue(); + } + + /** + * @param value The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. + */ + public Meta setVersionId(String value) { + if (Utilities.noString(value)) + this.versionId = null; + else { + if (this.versionId == null) + this.versionId = new IdType(); + this.versionId.setValue(value); + } + return this; + } + + /** + * @return {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value + */ + public InstantType getLastUpdatedElement() { + if (this.lastUpdated == null) + if (Configuration.errorOnAutoCreate()) + throw new Error("Attempt to auto-create Meta.lastUpdated"); + else if (Configuration.doAutoCreate()) + this.lastUpdated = new InstantType(); // bb + return this.lastUpdated; + } + + public boolean hasLastUpdatedElement() { + return this.lastUpdated != null && !this.lastUpdated.isEmpty(); + } + + public boolean hasLastUpdated() { + return this.lastUpdated != null && !this.lastUpdated.isEmpty(); + } + + /** + * @param value {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value + */ + public Meta setLastUpdatedElement(InstantType value) { + this.lastUpdated = value; + return this; + } + + /** + * @return When the resource last changed - e.g. when the version changed. + */ + public Date getLastUpdated() { + return this.lastUpdated == null ? null : this.lastUpdated.getValue(); + } + + /** + * @param value When the resource last changed - e.g. when the version changed. + */ + public Meta setLastUpdated(Date value) { + if (value == null) + this.lastUpdated = null; + else { + if (this.lastUpdated == null) + this.lastUpdated = new InstantType(); + this.lastUpdated.setValue(value); + } + return this; + } + + /** + * @return {@link #source} (A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.). This is the underlying object with id, value and extensions. The accessor "getSource" gives direct access to the value + */ + public UriType getSourceElement() { + if (this.source == null) + if (Configuration.errorOnAutoCreate()) + throw new Error("Attempt to auto-create Meta.source"); + else if (Configuration.doAutoCreate()) + this.source = new UriType(); // bb + return this.source; + } + + public boolean hasSourceElement() { + return this.source != null && !this.source.isEmpty(); + } + + public boolean hasSource() { + return this.source != null && !this.source.isEmpty(); + } + + /** + * @param value {@link #source} (A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.). This is the underlying object with id, value and extensions. The accessor "getSource" gives direct access to the value + */ + public Meta setSourceElement(UriType value) { + this.source = value; + return this; + } + + /** + * @return A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. + */ + public String getSource() { + return this.source == null ? null : this.source.getValue(); + } + + /** + * @param value A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. + */ + public Meta setSource(String value) { + if (Utilities.noString(value)) + this.source = null; + else { + if (this.source == null) + this.source = new UriType(); + this.source.setValue(value); + } + return this; + } + + /** + * @return {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) + */ + public List getProfile() { + if (this.profile == null) + this.profile = new ArrayList(); + return this.profile; + } + + /** + * @return Returns a reference to this for easy method chaining + */ + public Meta setProfile(List theProfile) { + this.profile = theProfile; + return this; + } + + public boolean hasProfile() { + if (this.profile == null) + return false; + for (CanonicalType item : this.profile) + if (!item.isEmpty()) + return true; + return false; + } + + /** + * @return {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) + */ + public CanonicalType addProfileElement() {//2 + CanonicalType t = new CanonicalType(); + if (this.profile == null) + this.profile = new ArrayList(); + this.profile.add(t); + return t; + } + + /** + * @param value {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) + */ + public Meta addProfile(String value) { //1 + CanonicalType t = new CanonicalType(); + t.setValue(value); + if (this.profile == null) + this.profile = new ArrayList(); + this.profile.add(t); + return this; + } + + /** + * @param value {@link #profile} (A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).) + */ + public boolean hasProfile(String value) { + if (this.profile == null) + return false; + for (CanonicalType v : this.profile) + if (v.getValue().equals(value)) // canonical + return true; + return false; + } + + /** + * @return {@link #security} (Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.) + */ + public List getSecurity() { + if (this.security == null) + this.security = new ArrayList(); + return this.security; + } + + /** + * @return Returns a reference to this for easy method chaining + */ + public Meta setSecurity(List theSecurity) { + this.security = theSecurity; + return this; + } + + public boolean hasSecurity() { + if (this.security == null) + return false; + for (Coding item : this.security) + if (!item.isEmpty()) + return true; + return false; + } + + public Coding addSecurity() { //3 + Coding t = new Coding(); + if (this.security == null) + this.security = new ArrayList(); + this.security.add(t); + return t; + } + + public Meta addSecurity(Coding t) { //3 + if (t == null) + return this; + if (this.security == null) + this.security = new ArrayList(); + this.security.add(t); + return this; + } + + /** + * @return The first repetition of repeating field {@link #security}, creating it if it does not already exist {3} + */ + public Coding getSecurityFirstRep() { + if (getSecurity().isEmpty()) { + addSecurity(); + } + return getSecurity().get(0); + } + + /** + * @return {@link #tag} (Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.) + */ + public List getTag() { + if (this.tag == null) + this.tag = new ArrayList(); + return this.tag; + } + + /** + * @return Returns a reference to this for easy method chaining + */ + public Meta setTag(List theTag) { + this.tag = theTag; + return this; + } + + public boolean hasTag() { + if (this.tag == null) + return false; + for (Coding item : this.tag) + if (!item.isEmpty()) + return true; + return false; + } + + public Coding addTag() { //3 + Coding t = new Coding(); + if (this.tag == null) + this.tag = new ArrayList(); + this.tag.add(t); + return t; + } + + public Meta addTag(Coding t) { //3 + if (t == null) + return this; + if (this.tag == null) + this.tag = new ArrayList(); + this.tag.add(t); + return this; + } + + /** + * @return The first repetition of repeating field {@link #tag}, creating it if it does not already exist {3} + */ + public Coding getTagFirstRep() { + if (getTag().isEmpty()) { + addTag(); + } + return getTag().get(0); + } + + protected void listChildren(List children) { + super.listChildren(children); + children.add(new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.", 0, 1, versionId)); + children.add(new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated)); + children.add(new Property("source", "uri", "A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.", 0, 1, source)); + children.add(new Property("profile", "canonical(StructureDefinition)", "A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).", 0, java.lang.Integer.MAX_VALUE, profile)); + children.add(new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security)); + children.add(new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag)); + } + + @Override + public Property getNamedProperty(int _hash, String _name, boolean _checkValid) throws FHIRException { + switch (_hash) { + case -1407102957: /*versionId*/ return new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted.", 0, 1, versionId); + case 1649733957: /*lastUpdated*/ return new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated); + case -896505829: /*source*/ return new Property("source", "uri", "A uri that identifies the source system of the resource. This provides a minimal amount of [Provenance](provenance.html#) information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc.", 0, 1, source); + case -309425751: /*profile*/ return new Property("profile", "canonical(StructureDefinition)", "A list of profiles (references to [StructureDefinition](structuredefinition.html#) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](structuredefinition-definitions.html#StructureDefinition.url).", 0, java.lang.Integer.MAX_VALUE, profile); + case 949122880: /*security*/ return new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security); + case 114586: /*tag*/ return new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag); + default: return super.getNamedProperty(_hash, _name, _checkValid); + } + + } + + @Override + public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException { + switch (hash) { + case -1407102957: /*versionId*/ return this.versionId == null ? new Base[0] : new Base[] {this.versionId}; // IdType + case 1649733957: /*lastUpdated*/ return this.lastUpdated == null ? new Base[0] : new Base[] {this.lastUpdated}; // InstantType + case -896505829: /*source*/ return this.source == null ? new Base[0] : new Base[] {this.source}; // UriType + case -309425751: /*profile*/ return this.profile == null ? new Base[0] : this.profile.toArray(new Base[this.profile.size()]); // CanonicalType + case 949122880: /*security*/ return this.security == null ? new Base[0] : this.security.toArray(new Base[this.security.size()]); // Coding + case 114586: /*tag*/ return this.tag == null ? new Base[0] : this.tag.toArray(new Base[this.tag.size()]); // Coding + default: return super.getProperty(hash, name, checkValid); + } + + } + + @Override + public Base setProperty(int hash, String name, Base value) throws FHIRException { + switch (hash) { + case -1407102957: // versionId + this.versionId = TypeConvertor.castToId(value); // IdType + return value; + case 1649733957: // lastUpdated + this.lastUpdated = TypeConvertor.castToInstant(value); // InstantType + return value; + case -896505829: // source + this.source = TypeConvertor.castToUri(value); // UriType + return value; + case -309425751: // profile + this.getProfile().add(TypeConvertor.castToCanonical(value)); // CanonicalType + return value; + case 949122880: // security + this.getSecurity().add(TypeConvertor.castToCoding(value)); // Coding + return value; + case 114586: // tag + this.getTag().add(TypeConvertor.castToCoding(value)); // Coding + return value; + default: return super.setProperty(hash, name, value); + } + + } + + @Override + public Base setProperty(String name, Base value) throws FHIRException { + if (name.equals("versionId")) { + this.versionId = TypeConvertor.castToId(value); // IdType + } else if (name.equals("lastUpdated")) { + this.lastUpdated = TypeConvertor.castToInstant(value); // InstantType + } else if (name.equals("source")) { + this.source = TypeConvertor.castToUri(value); // UriType + } else if (name.equals("profile")) { + this.getProfile().add(TypeConvertor.castToCanonical(value)); + } else if (name.equals("security")) { + this.getSecurity().add(TypeConvertor.castToCoding(value)); + } else if (name.equals("tag")) { + this.getTag().add(TypeConvertor.castToCoding(value)); + } else + return super.setProperty(name, value); + return value; + } + + @Override + public Base makeProperty(int hash, String name) throws FHIRException { + switch (hash) { + case -1407102957: return getVersionIdElement(); + case 1649733957: return getLastUpdatedElement(); + case -896505829: return getSourceElement(); + case -309425751: return addProfileElement(); + case 949122880: return addSecurity(); + case 114586: return addTag(); + default: return super.makeProperty(hash, name); + } + + } + + @Override + public String[] getTypesForProperty(int hash, String name) throws FHIRException { + switch (hash) { + case -1407102957: /*versionId*/ return new String[] {"id"}; + case 1649733957: /*lastUpdated*/ return new String[] {"instant"}; + case -896505829: /*source*/ return new String[] {"uri"}; + case -309425751: /*profile*/ return new String[] {"canonical"}; + case 949122880: /*security*/ return new String[] {"Coding"}; + case 114586: /*tag*/ return new String[] {"Coding"}; + default: return super.getTypesForProperty(hash, name); + } + + } + + @Override + public Base addChild(String name) throws FHIRException { + if (name.equals("versionId")) { + throw new FHIRException("Cannot call addChild on a primitive type Meta.versionId"); + } + else if (name.equals("lastUpdated")) { + throw new FHIRException("Cannot call addChild on a primitive type Meta.lastUpdated"); + } + else if (name.equals("source")) { + throw new FHIRException("Cannot call addChild on a primitive type Meta.source"); + } + else if (name.equals("profile")) { + throw new FHIRException("Cannot call addChild on a primitive type Meta.profile"); + } + else if (name.equals("security")) { + return addSecurity(); + } + else if (name.equals("tag")) { + return addTag(); + } + else + return super.addChild(name); + } + + public String fhirType() { + return "Meta"; + + } + + public Meta copy() { + Meta dst = new Meta(); + copyValues(dst); + return dst; + } + + public void copyValues(Meta dst) { + super.copyValues(dst); + dst.versionId = versionId == null ? null : versionId.copy(); + dst.lastUpdated = lastUpdated == null ? null : lastUpdated.copy(); + dst.source = source == null ? null : source.copy(); + if (profile != null) { + dst.profile = new ArrayList(); + for (CanonicalType i : profile) + dst.profile.add(i.copy()); + }; + if (security != null) { + dst.security = new ArrayList(); + for (Coding i : security) + dst.security.add(i.copy()); + }; + if (tag != null) { + dst.tag = new ArrayList(); + for (Coding i : tag) + dst.tag.add(i.copy()); + }; + } + + protected Meta typedCopy() { + return copy(); + } + + @Override + public boolean equalsDeep(Base other_) { + if (!super.equalsDeep(other_)) + return false; + if (!(other_ instanceof Meta)) + return false; + Meta o = (Meta) other_; + return compareDeep(versionId, o.versionId, true) && compareDeep(lastUpdated, o.lastUpdated, true) + && compareDeep(source, o.source, true) && compareDeep(profile, o.profile, true) && compareDeep(security, o.security, true) + && compareDeep(tag, o.tag, true); + } + + @Override + public boolean equalsShallow(Base other_) { + if (!super.equalsShallow(other_)) + return false; + if (!(other_ instanceof Meta)) + return false; + Meta o = (Meta) other_; + return compareValues(versionId, o.versionId, true) && compareValues(lastUpdated, o.lastUpdated, true) + && compareValues(source, o.source, true) && compareValues(profile, o.profile, true); + } + + public boolean isEmpty() { + return super.isEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty(versionId, lastUpdated, source + , profile, security, tag); + } + +// Manual code (from Configuration.txt)t: + /** + * Convenience method which adds a tag + * + * @param theSystem The code system + * @param theCode The code + * @param theDisplay The display name + * @return Returns a reference to this for easy chaining + */ + public Meta addTag(String theSystem, String theCode, String theDisplay) { + addTag().setSystem(theSystem).setCode(theCode).setDisplay(theDisplay); + return this; + } + + /** + * Returns the first tag (if any) that has the given system and code, or returns + * null if none + */ + public Coding getTag(String theSystem, String theCode) { + for (Coding next : getTag()) { + if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { + return next; + } + } + return null; + } + + /** + * Returns the first security label (if any) that has the given system and code, or returns + * null if none + */ + public Coding getSecurity(String theSystem, String theCode) { + for (Coding next : getSecurity()) { + if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { + return next; + } + } + return null; + } + +// end addition + +} + diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/MetaTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/MetaTest.java new file mode 100644 index 000000000..b311fca3a --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/MetaTest.java @@ -0,0 +1,26 @@ +package org.hl7.fhir.r5.test; + +import org.hl7.fhir.r5.model.Coding; +import org.hl7.fhir.r5.model.Meta; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +public class MetaTest { + public static String TEST_SYSTEM = "TEST_SYSTEM"; + public static String TEST_CODE = "TEST_CODE"; + + @Test + public void testMetaSecurity() { + Meta meta = new Meta(); + Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE); + assertTrue(meta.hasSecurity()); + assertNotNull(meta.getSecurity()); + assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(1, meta.getSecurity().size()); + assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE)); + } +} From bd40310684ffb62905ae45de027aa056f96c83ea Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:19:04 +1100 Subject: [PATCH 39/44] fix getSecurity --- org.hl7.fhir.core.generator/configuration/Meta.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.core.generator/configuration/Meta.java b/org.hl7.fhir.core.generator/configuration/Meta.java index 7137bf15b..e875d789c 100644 --- a/org.hl7.fhir.core.generator/configuration/Meta.java +++ b/org.hl7.fhir.core.generator/configuration/Meta.java @@ -29,7 +29,7 @@ * null if none */ public Coding getSecurity(String theSystem, String theCode) { - for (Coding next : getTag()) { + for (Coding next : getSecurity()) { if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) { return next; } From 42853db49372d5e25eb7c4009fe9542060796a56 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:20:01 +1100 Subject: [PATCH 40/44] fix version conversion for OperationDefinition --- .../hl7/fhir/convertors/VersionConvertor_30_50.java | 12 ++++++++++++ .../conv30_50/OperationDefinition30_50.java | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java index 9a3395139..cdcae2810 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/VersionConvertor_30_50.java @@ -316,6 +316,18 @@ public class VersionConvertor_30_50 { return tgt; } + public static org.hl7.fhir.r5.model.MarkdownType convertStringToMarkdown(org.hl7.fhir.dstu3.model.StringType src) throws FHIRException { + org.hl7.fhir.r5.model.MarkdownType tgt = new org.hl7.fhir.r5.model.MarkdownType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + + public static org.hl7.fhir.dstu3.model.StringType convertMarkdownToString(org.hl7.fhir.r5.model.MarkdownType src) throws FHIRException { + org.hl7.fhir.dstu3.model.StringType tgt = new org.hl7.fhir.dstu3.model.StringType(src.getValue()); + copyElement(src, tgt); + return tgt; + } + public static org.hl7.fhir.r5.model.TimeType convertTime(org.hl7.fhir.dstu3.model.TimeType src) throws FHIRException { org.hl7.fhir.r5.model.TimeType tgt = new org.hl7.fhir.r5.model.TimeType(src.getValue()); copyElement(src, tgt); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/OperationDefinition30_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/OperationDefinition30_50.java index e9fbe4376..4dc0430cd 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/OperationDefinition30_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/OperationDefinition30_50.java @@ -49,7 +49,7 @@ public class OperationDefinition30_50 { if (src.hasCodeElement()) tgt.setCodeElement((org.hl7.fhir.r5.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement())); if (src.hasCommentElement()) - tgt.setCommentElement((org.hl7.fhir.r5.model.MarkdownType) VersionConvertor_30_50.convertType(src.getCommentElement())); + tgt.setCommentElement(VersionConvertor_30_50.convertStringToMarkdown(src.getCommentElement())); if (src.hasBase()) tgt.setBaseElement(VersionConvertor_30_50.convertReferenceToCanonical(src.getBase())); if (src.hasResource()) { @@ -109,7 +109,7 @@ public class OperationDefinition30_50 { if (src.hasCodeElement()) tgt.setCodeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement())); if (src.hasCommentElement()) - tgt.setCommentElement((org.hl7.fhir.dstu3.model.StringType) VersionConvertor_30_50.convertType(src.getCommentElement())); + tgt.setCommentElement(VersionConvertor_30_50.convertMarkdownToString(src.getCommentElement())); if (src.hasBase()) tgt.setBase(VersionConvertor_30_50.convertCanonicalToReference(src.getBaseElement())); if (src.hasResource()) { From db2c862b1e3134a9652f796c9e436e2ca749ccb8 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:21:07 +1100 Subject: [PATCH 41/44] workaround NPE in summary renderer --- .../fhir/r5/conformance/ProfileUtilities.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index c80cc3877..f2d8742ec 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -5311,14 +5311,18 @@ public class ProfileUtilities extends TranslatingUtilities { private String getCardinality(ElementDefinition ed, List list) { int min = ed.getMin(); int max = !ed.hasMax() || ed.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(ed.getMax()); - while (ed != null && ed.getPath().contains(".")) { - ed = findParent(ed, list); - if (ed.getMax().equals("0")) - max = 0; - else if (!ed.getMax().equals("1") && !ed.hasSlicing()) - max = Integer.MAX_VALUE; - if (ed.getMin() == 0) - min = 0; + ElementDefinition ned = ed; + while (ned != null && ned.getPath().contains(".")) { + ned = findParent(ned, list); + if (ned != null) { // todo: this can happen if we've walked into a resoruce. Not sure what to about that? + if ("0".equals(ned.getMax())) + max = 0; + else if (!ned.getMax().equals("1") && !ned.hasSlicing()) + max = Integer.MAX_VALUE; + if (ned.getMin() == 0) { + min = 0; + } + } } return Integer.toString(min)+".."+(max == Integer.MAX_VALUE ? "*" : Integer.toString(max)); } From 49a66fe760ef4278d05887fa5ffbc00edb4956c9 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:22:11 +1100 Subject: [PATCH 42/44] fix language to appear in all NarrativeGenerator modes --- .../org/hl7/fhir/r5/utils/NarrativeGenerator.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java index 0dd6c90d6..20053c157 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java @@ -1620,6 +1620,8 @@ public class NarrativeGenerator implements INarrativeGenerator { return false; } else if (e instanceof ElementDefinition) { return false; + } else if (e instanceof Base64BinaryType) { + return false; } else if (!(e instanceof Attachment)) throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet"); return false; @@ -2541,6 +2543,13 @@ public class NarrativeGenerator implements INarrativeGenerator { private void inject(Element er, XhtmlNode x, NarrativeStatus status) { if (!x.hasAttribute("xmlns")) x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + Element le = XMLUtil.getNamedChild(er, "language"); + String l = le == null ? null : le.getAttribute("value"); + if (!Utilities.noString(l)) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", l); + x.setAttribute("xml:lang", l); + } Element txt = XMLUtil.getNamedChild(er, "text"); if (txt == null) { txt = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text"); @@ -2576,6 +2585,12 @@ public class NarrativeGenerator implements INarrativeGenerator { private void inject(org.hl7.fhir.r5.elementmodel.Element er, XhtmlNode x, NarrativeStatus status) throws IOException, FHIRException { if (!x.hasAttribute("xmlns")) x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + String l = er.getChildValue("language"); + if (!Utilities.noString(l)) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", l); + x.setAttribute("xml:lang", l); + } org.hl7.fhir.r5.elementmodel.Element txt = er.getNamedChild("text"); if (txt == null) { txt = new org.hl7.fhir.r5.elementmodel.Element("text", er.getProperty().getChild(null, "text")); From 44d41ee523a966e91434255d9a92d137fda7b867 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:22:54 +1100 Subject: [PATCH 43/44] register additional tests --- .../src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java | 1 + .../src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java | 3 ++- release.bat | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java index f6191b0f2..5bf6c714c 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/AllR5Tests.java @@ -23,6 +23,7 @@ import org.junit.runners.Suite.SuiteClasses; BaseDateTimeTypeTest.class, OpenApiGeneratorTest.class, MetadataResourceManagerTester.class, + MetaTest.class, UtilitiesTests.class, SnapShotGenerationTests.class}) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java index 66c4416a9..b245d4afc 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/UtilitiesTests.java @@ -1,6 +1,7 @@ package org.hl7.fhir.r5.test; import java.io.IOException; +import org.apache.commons.lang3.SystemUtils; import org.hl7.fhir.utilities.Utilities; import org.junit.Test; @@ -11,7 +12,7 @@ public class UtilitiesTests { @Test public void testPath() throws IOException { - Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), "c:\\temp\\test.txt"); + Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), SystemUtils.IS_OS_WINDOWS ? "c:\\temp\\test.txt" : "/temp/test.txt"); Assert.assertEquals(Utilities.path("[user]", "test.txt"), System.getProperty("user.home")+"\\test.txt"); Assert.assertEquals(Utilities.path("[JAVA_HOME]", "test.txt"), System.getenv("JAVA_HOME")+"\\test.txt"); } diff --git a/release.bat b/release.bat index 8edc066df..705099797 100644 --- a/release.bat +++ b/release.bat @@ -37,8 +37,6 @@ call python c:\tools\zulip-api\zulip\zulip\send.py --stream tooling/releases --s del C:\temp\current-release-notes-validator.md -pause - :DONE echo =============================================================== echo all done From 17eb1c41f7300f6e407cb043ed8b27d1ed2b3783 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 13 Feb 2020 21:23:40 +1100 Subject: [PATCH 44/44] Release new version 4.1.63 --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- release.bat | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index c1e63c036..62ed319f9 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 529b24eee..eb66cb271 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 903d562d8..2a22e1068 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index ee11d9a4d..d15a6299b 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 7d660914f..b5d82f7ab 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index e76dde00e..667c503f7 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 12e7367f8..4bf772ba6 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index d94fc7238..91e1653f4 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 2a5d1b378..dcadc3ebc 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 8690acbcd..cf55740ef 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ each other. It is fine to bump the point version of this POM without affecting HAPI FHIR. --> - 4.1.62-SNAPSHOT + 4.1.63-SNAPSHOT 4.1.0 diff --git a/release.bat b/release.bat index 705099797..243f1a4b6 100644 --- a/release.bat +++ b/release.bat @@ -1,7 +1,7 @@ @echo off -set oldver=4.1.61 -set newver=4.1.62 +set oldver=4.1.62 +set newver=4.1.63 echo .. echo =====================================================================