report slicing information automatically where slicing is based on profile + fix shc support + support codesystem-properties-mode + fix value set validation on profiles + fix wrong entry point on vaildating contained resources with profiles
This commit is contained in:
parent
4ff3c45fca
commit
a8ba0ed4e5
|
@ -514,6 +514,7 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
||||||
public String[] sliceText;
|
public String[] sliceText;
|
||||||
private boolean slicingHint;
|
private boolean slicingHint;
|
||||||
private boolean signpost;
|
private boolean signpost;
|
||||||
|
private boolean criticalSignpost;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -772,9 +773,10 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
||||||
return sliceHtml;
|
return sliceHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSliceHtml(String sliceHtml, String[] text) {
|
public ValidationMessage setSliceHtml(String sliceHtml, String[] text) {
|
||||||
this.sliceHtml = sliceHtml;
|
this.sliceHtml = sliceHtml;
|
||||||
this.sliceText = text;
|
this.sliceText = text;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessageId() {
|
public String getMessageId() {
|
||||||
|
@ -795,5 +797,14 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCriticalSignpost() {
|
||||||
|
return criticalSignpost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationMessage setCriticalSignpost(boolean criticalSignpost) {
|
||||||
|
this.criticalSignpost = criticalSignpost;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,7 +2,11 @@ package org.hl7.fhir.validation;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -262,9 +266,9 @@ public class BaseValidator {
|
||||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||||
*/
|
*/
|
||||||
//FIXME: formatMessage should be done here
|
//FIXME: formatMessage should be done here
|
||||||
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html, String[] text) {
|
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, boolean isCritical, String msg, String html, String[] text) {
|
||||||
if (!thePass) {
|
if (!thePass) {
|
||||||
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text);
|
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text).setCriticalSignpost(isCritical);
|
||||||
}
|
}
|
||||||
return thePass;
|
return thePass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,8 @@ public class IgLoader {
|
||||||
res.cntType = Manager.FhirFormat.XML;
|
res.cntType = Manager.FhirFormat.XML;
|
||||||
else if (t.getKey().endsWith(".ttl"))
|
else if (t.getKey().endsWith(".ttl"))
|
||||||
res.cntType = Manager.FhirFormat.TURTLE;
|
res.cntType = Manager.FhirFormat.TURTLE;
|
||||||
|
else if (t.getKey().endsWith(".shc"))
|
||||||
|
res.cntType = Manager.FhirFormat.SHC;
|
||||||
else if (t.getKey().endsWith(".txt") || t.getKey().endsWith(".map"))
|
else if (t.getKey().endsWith(".txt") || t.getKey().endsWith(".map"))
|
||||||
res.cntType = Manager.FhirFormat.TEXT;
|
res.cntType = Manager.FhirFormat.TEXT;
|
||||||
else
|
else
|
||||||
|
|
|
@ -293,14 +293,10 @@ public class ValidationService {
|
||||||
System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes");
|
System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes");
|
||||||
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
|
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
|
||||||
System.out.println(getIssueSummary(issue));
|
System.out.println(getIssueSummary(issue));
|
||||||
if (crumbs) {
|
ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg");
|
||||||
ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg");
|
if (vm != null && vm.sliceText != null && (crumbs || vm.isCriticalSignpost())) {
|
||||||
if (vm != null) {
|
for (String s : vm.sliceText) {
|
||||||
if (vm.sliceText != null) {
|
System.out.println(" slice info: "+s);
|
||||||
for (String s : vm.sliceText) {
|
|
||||||
System.out.println(" slice info: "+s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation;
|
import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||||
|
@ -303,7 +304,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
} else if (item instanceof Element) {
|
} else if (item instanceof Element) {
|
||||||
Element e = (Element) item;
|
Element e = (Element) item;
|
||||||
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
if (e.getName().equals("contained")) {
|
||||||
|
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||||
|
} else {
|
||||||
|
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
throw new NotImplementedException(context.formatMessage(I18nConstants.NOT_DONE_YET_VALIDATORHOSTSERVICESCONFORMSTOPROFILE_WHEN_ITEM_IS_NOT_AN_ELEMENT));
|
throw new NotImplementedException(context.formatMessage(I18nConstants.NOT_DONE_YET_VALIDATORHOSTSERVICESCONFORMSTOPROFILE_WHEN_ITEM_IS_NOT_AN_ELEMENT));
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
|
@ -2753,7 +2758,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (!isShowMessagesFromReferences()) {
|
if (!isShowMessagesFromReferences()) {
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
|
||||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||||
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false,
|
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false,
|
||||||
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
||||||
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
||||||
}
|
}
|
||||||
|
@ -2771,7 +2776,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (!isShowMessagesFromReferences()) {
|
if (!isShowMessagesFromReferences()) {
|
||||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
|
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
|
||||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||||
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
||||||
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2898,6 +2903,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return "<ul>" + b.toString() + "</ul>";
|
return "<ul>" + b.toString() + "</ul>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isCritical(List<ValidationMessage> list) {
|
||||||
|
for (ValidationMessage vm : list) {
|
||||||
|
if (vm.isSlicingHint() && vm.isCriticalSignpost()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private String[] errorSummaryForSlicingAsText(List<ValidationMessage> list) {
|
private String[] errorSummaryForSlicingAsText(List<ValidationMessage> list) {
|
||||||
List<String> res = new ArrayList<String>();
|
List<String> res = new ArrayList<String>();
|
||||||
for (ValidationMessage vm : list) {
|
for (ValidationMessage vm : list) {
|
||||||
|
@ -3305,7 +3319,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
rr.setExternal(false);
|
rr.setExternal(false);
|
||||||
rr.setStack(nstack);
|
rr.setStack(nstack);
|
||||||
// rr.getStack().qualifyPath(".ofType("+nstack.getElement().fhirType()+")");
|
// rr.getStack().qualifyPath(".ofType("+nstack.getElement().fhirType()+")");
|
||||||
System.out.println("-->"+nstack.getLiteralPath());
|
// System.out.println("-->"+nstack.getLiteralPath());
|
||||||
return rr;
|
return rr;
|
||||||
}
|
}
|
||||||
if (nstack.getElement().getSpecial() == SpecialElement.CONTAINED) {
|
if (nstack.getElement().getSpecial() == SpecialElement.CONTAINED) {
|
||||||
|
@ -3675,9 +3689,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
ValidatorHostContext shc = hostContext.forSlicing();
|
ValidatorHostContext shc = hostContext.forSlicing();
|
||||||
boolean pass = evaluateSlicingExpression(shc, element, path, profile, n);
|
boolean pass = evaluateSlicingExpression(shc, element, path, profile, n);
|
||||||
if (!pass) {
|
if (!pass) {
|
||||||
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()), null);
|
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, isProfile(slicer), (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()), null);
|
||||||
for (String url : shc.getSliceRecords().keySet()) {
|
for (String url : shc.getSliceRecords().keySet()) {
|
||||||
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false,
|
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, isProfile(slicer),
|
||||||
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, stack.getLiteralPath(), url),
|
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, stack.getLiteralPath(), url),
|
||||||
context.formatMessage(I18nConstants.PROFILE__DOES_NOT_MATCH_FOR__BECAUSE_OF_THE_FOLLOWING_PROFILE_ISSUES__,
|
context.formatMessage(I18nConstants.PROFILE__DOES_NOT_MATCH_FOR__BECAUSE_OF_THE_FOLLOWING_PROFILE_ISSUES__,
|
||||||
url,
|
url,
|
||||||
|
@ -3687,6 +3701,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isProfile(ElementDefinition slicer) {
|
||||||
|
if (slicer == null || !slicer.hasSlicing()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ElementDefinitionSlicingDiscriminatorComponent t : slicer.getSlicing().getDiscriminator()) {
|
||||||
|
if (t.getType() == DiscriminatorType.PROFILE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException {
|
public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException {
|
||||||
String msg;
|
String msg;
|
||||||
boolean ok;
|
boolean ok;
|
||||||
|
@ -4898,7 +4924,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (ei.additionalSlice && ei.definition != null) {
|
if (ei.additionalSlice && ei.definition != null) {
|
||||||
if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) ||
|
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" */) {
|
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.getPath(), false,
|
slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.getPath(), false, isProfile(slicer) || isCritical(ei.sliceInfo),
|
||||||
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_,
|
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_,
|
||||||
profile == null ? "" : " defined in the profile " + profile.getUrl()),
|
profile == null ? "" : " defined in the profile " + profile.getUrl()),
|
||||||
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo),
|
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo),
|
||||||
|
@ -4944,6 +4970,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return problematicPaths;
|
return problematicPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<ElementInfo> listChildren(Element element, NodeStack stack) {
|
public List<ElementInfo> listChildren(Element element, NodeStack stack) {
|
||||||
// 1. List the children, and remember their exact path (convenience)
|
// 1. List the children, and remember their exact path (convenience)
|
||||||
List<ElementInfo> children = new ArrayList<ElementInfo>();
|
List<ElementInfo> children = new ArrayList<ElementInfo>();
|
||||||
|
@ -5197,7 +5224,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
// todo: validate everything in this bundle.
|
// todo: validate everything in this bundle.
|
||||||
}
|
}
|
||||||
ok = rule(errors, IssueType.INVALID, -1, -1, stack.getLiteralPath(), typeMatchesDefn(resourceName, defn), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE, defn.getName(), resourceName);
|
ok = rule(errors, IssueType.INVALID, -1, -1, stack.getLiteralPath(), typeMatchesDefn(resourceName, defn), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE, defn.getType(), resourceName, defn.getName());
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (idstatus == IdStatus.REQUIRED && (element.getNamedChild(ID) == null)) {
|
if (idstatus == IdStatus.REQUIRED && (element.getNamedChild(ID) == null)) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,10 +15,12 @@ import org.hl7.fhir.convertors.factory.*;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r5.model.ExpressionNode;
|
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
@ -35,6 +37,7 @@ import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.hl7.fhir.validation.BaseValidator;
|
import org.hl7.fhir.validation.BaseValidator;
|
||||||
import org.hl7.fhir.validation.TimeTracker;
|
import org.hl7.fhir.validation.TimeTracker;
|
||||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||||
|
@ -209,13 +212,23 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference");
|
String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference");
|
||||||
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
||||||
Resource vs = context.fetchResource(Resource.class, ref);
|
Resource vs = context.fetchResource(Resource.class, ref);
|
||||||
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null, I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
|
||||||
rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType());
|
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
|
||||||
|
|
||||||
|
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serversSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||||
|
if (vs != null) {
|
||||||
|
rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean serversSupportsValueSet(String ref) {
|
||||||
|
ValidationResult vr = context.validateCode(new ValidationOptions().checkValueSetOnly().setVsAsUrl().noClient(), new Coding("http://loinc.org", "5792-7", null), new ValueSet().setUrl(ref));
|
||||||
|
return vr.getErrorClass() == null;
|
||||||
|
}
|
||||||
|
|
||||||
private void validateElementType(List<ValidationMessage> errors, Element type, NodeStack stack, StructureDefinition sd, String path) {
|
private void validateElementType(List<ValidationMessage> errors, Element type, NodeStack stack, StructureDefinition sd, String path) {
|
||||||
String code = type.getNamedChildValue("code");
|
String code = type.getNamedChildValue("code");
|
||||||
if (code == null && path != null) {
|
if (code == null && path != null) {
|
||||||
|
|
|
@ -26,11 +26,20 @@ public class ValidatorHostContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidatorHostContext(Object appContext, Element element) {
|
public ValidatorHostContext(Object appContext, Element element) {
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.resource = element;
|
this.resource = element;
|
||||||
this.rootResource = element;
|
this.rootResource = element;
|
||||||
// no container
|
// no container
|
||||||
}
|
dump("creating");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidatorHostContext(Object appContext, Element element, Element root) {
|
||||||
|
this.appContext = appContext;
|
||||||
|
this.resource = element;
|
||||||
|
this.rootResource = root;
|
||||||
|
// no container
|
||||||
|
dump("creating");
|
||||||
|
}
|
||||||
|
|
||||||
public Object getAppContext() {
|
public Object getAppContext() {
|
||||||
return appContext;
|
return appContext;
|
||||||
|
@ -52,6 +61,7 @@ public class ValidatorHostContext {
|
||||||
|
|
||||||
public ValidatorHostContext setRootResource(Element rootResource) {
|
public ValidatorHostContext setRootResource(Element rootResource) {
|
||||||
this.rootResource = rootResource;
|
this.rootResource = rootResource;
|
||||||
|
dump("setting root resource");
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +106,7 @@ public class ValidatorHostContext {
|
||||||
res.rootResource = resource;
|
res.rootResource = resource;
|
||||||
res.resource = element;
|
res.resource = element;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
|
res.dump("forContained");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +115,7 @@ public class ValidatorHostContext {
|
||||||
res.rootResource = element;
|
res.rootResource = element;
|
||||||
res.resource = element;
|
res.resource = element;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
|
res.dump("forEntry");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +125,7 @@ public class ValidatorHostContext {
|
||||||
res.rootResource = rootResource;
|
res.rootResource = rootResource;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
|
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
|
||||||
|
res.dump("forProfile "+profile.getUrl());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,15 +135,24 @@ public class ValidatorHostContext {
|
||||||
res.rootResource = resource;
|
res.rootResource = resource;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
res.checkSpecials = false;
|
res.checkSpecials = false;
|
||||||
|
res.dump("forLocalReference "+profile.getUrl());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void dump(String ctxt) {
|
||||||
|
// System.out.println("** app = "+(appContext == null ? "(null)" : appContext.toString())+", res = "+resource.toString()+", root = "+rootResource.toString()+" ("+ctxt+")");
|
||||||
|
// if (rootResource.getName().equals("contained")) {
|
||||||
|
// System.out.println("** something is wrong!");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
public ValidatorHostContext forRemoteReference(StructureDefinition profile, Element resource) {
|
public ValidatorHostContext forRemoteReference(StructureDefinition profile, Element resource) {
|
||||||
ValidatorHostContext res = new ValidatorHostContext(appContext);
|
ValidatorHostContext res = new ValidatorHostContext(appContext);
|
||||||
res.resource = resource;
|
res.resource = resource;
|
||||||
res.rootResource = resource;
|
res.rootResource = resource;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
res.checkSpecials = false;
|
res.checkSpecials = false;
|
||||||
|
res.dump("forRemoteReference "+profile.getUrl());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +163,7 @@ public class ValidatorHostContext {
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
res.checkSpecials = false;
|
res.checkSpecials = false;
|
||||||
res.sliceRecords = new HashMap<String, List<ValidationMessage>>();
|
res.sliceRecords = new HashMap<String, List<ValidationMessage>>();
|
||||||
|
res.dump("forSlicing");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue