enforce constraints in slicer as well as in slice + Handle -tx n/a better

This commit is contained in:
Grahame Grieve 2020-10-14 13:16:59 +11:00
parent d20582ca9d
commit 920c3193d0
3 changed files with 269 additions and 229 deletions

View File

@ -49,6 +49,7 @@ import org.apache.commons.lang3.StringUtils;
import org.fhir.ucum.UcumService; import org.fhir.ucum.UcumService;
import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.NoTerminologyServiceException;
import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
@ -910,6 +911,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT); txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
return res; return res;
} catch (Exception e) { } catch (Exception e) {
if (e instanceof NoTerminologyServiceException) {
return new ValidationResult(IssueSeverity.ERROR, "No Terminology Service", TerminologyServiceErrorClass.NOSERVICE);
}
} }
} }

View File

@ -37,6 +37,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.NoTerminologyServiceException;
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.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CanonicalType;
@ -515,6 +516,9 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) { if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
return null; return null;
} }
if (res.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
throw new NoTerminologyServiceException();
}
return res.isOk(); return res.isOk();
} else { } else {
if (vsi.hasFilter()) { if (vsi.hasFilter()) {

View File

@ -37,10 +37,8 @@ import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -51,15 +49,10 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.convertors.*;
import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
@ -86,6 +79,7 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ContactPoint; import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DateTimeType; import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.DateType; import org.hl7.fhir.r5.model.DateType;
import org.hl7.fhir.r5.model.DecimalType; import org.hl7.fhir.r5.model.DecimalType;
@ -114,6 +108,7 @@ import org.hl7.fhir.r5.model.PrimitiveType;
import org.hl7.fhir.r5.model.Quantity; import org.hl7.fhir.r5.model.Quantity;
import org.hl7.fhir.r5.model.Range; import org.hl7.fhir.r5.model.Range;
import org.hl7.fhir.r5.model.Ratio; import org.hl7.fhir.r5.model.Ratio;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.SampledData; import org.hl7.fhir.r5.model.SampledData;
import org.hl7.fhir.r5.model.SearchParameter; import org.hl7.fhir.r5.model.SearchParameter;
@ -127,18 +122,30 @@ import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionSnapshotComp
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.TimeType; import org.hl7.fhir.r5.model.TimeType;
import org.hl7.fhir.r5.model.Timing; import org.hl7.fhir.r5.model.Timing;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.TypeDetails; import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.model.UriType; import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException; import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.IResourceValidator; import org.hl7.fhir.r5.utils.IResourceValidator;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.Utilities.DecimalStatus;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.validation.BaseValidator; import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.Validator.QuestionnaireMode; import org.hl7.fhir.validation.Validator.QuestionnaireMode;
import org.hl7.fhir.validation.instance.type.BundleValidator; import org.hl7.fhir.validation.instance.type.BundleValidator;
@ -148,19 +155,13 @@ import org.hl7.fhir.validation.instance.type.QuestionnaireValidator;
import org.hl7.fhir.validation.instance.type.SearchParameterValidator; import org.hl7.fhir.validation.instance.type.SearchParameterValidator;
import org.hl7.fhir.validation.instance.type.StructureDefinitionValidator; import org.hl7.fhir.validation.instance.type.StructureDefinitionValidator;
import org.hl7.fhir.validation.instance.type.ValueSetValidator; import org.hl7.fhir.validation.instance.type.ValueSetValidator;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.validation.instance.utils.ChildIterator;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.validation.instance.utils.ElementInfo;
import org.hl7.fhir.utilities.Utilities.DecimalStatus; import org.hl7.fhir.validation.instance.utils.IndexedElement;
import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.validation.instance.utils.NodeStack;
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo; import org.hl7.fhir.validation.instance.utils.ResolvedReference;
import org.hl7.fhir.utilities.validation.ValidationOptions; import org.hl7.fhir.validation.instance.utils.ResourceValidationTracker;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.validation.instance.utils.*;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import com.google.gson.Gson; import com.google.gson.Gson;
@ -343,6 +344,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private String validationLanguage; private String validationLanguage;
private boolean baseOnly; private boolean baseOnly;
private boolean noCheckAggregation; private boolean noCheckAggregation;
private boolean wantCheckSnapshotUnchanged;
private List<ImplementationGuide> igs = new ArrayList<>(); private List<ImplementationGuide> igs = new ArrayList<>();
private List<String> extensionDomains = new ArrayList<String>(); private List<String> extensionDomains = new ArrayList<String>();
@ -1004,7 +1006,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ValidationResult vr = checkCodeOnServer(stack, valueset, cc, true); // we're going to validate the codings directly, so only check the valueset ValidationResult vr = checkCodeOnServer(stack, valueset, cc, true); // we're going to validate the codings directly, so only check the valueset
if (!vr.isOk()) { if (!vr.isOk()) {
bindingsOk = false; bindingsOk = false;
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) { if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
if (binding.getStrength() == BindingStrength.REQUIRED || (binding.getStrength() == BindingStrength.EXTENSIBLE && binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))) {
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOSVC_BOUND_REQ, describeReference(binding.getValueSet()));
} else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOSVC_BOUND_EXT, describeReference(binding.getValueSet()));
}
} else if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
if (binding.getStrength() == BindingStrength.REQUIRED) if (binding.getStrength() == BindingStrength.REQUIRED)
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1, describeReference(binding.getValueSet()), vr.getErrorClass().toString());
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
@ -3860,7 +3868,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (element.getType().equals("SearchParameter")) { } else if (element.getType().equals("SearchParameter")) {
new SearchParameterValidator(context, timeTracker, fpe).validateSearchParameter(errors, element, stack); new SearchParameterValidator(context, timeTracker, fpe).validateSearchParameter(errors, element, stack);
} else if (element.getType().equals("StructureDefinition")) { } else if (element.getType().equals("StructureDefinition")) {
new StructureDefinitionValidator(context, timeTracker, fpe).validateStructureDefinition(errors, element, stack); new StructureDefinitionValidator(context, timeTracker, fpe, wantCheckSnapshotUnchanged).validateStructureDefinition(errors, element, stack);
} else if (element.getType().equals("ValueSet")) { } else if (element.getType().equals("ValueSet")) {
new ValueSetValidator(context, timeTracker, this).validateValueSet(errors, element, stack); new ValueSetValidator(context, timeTracker, this).validateValueSet(errors, element, stack);
} }
@ -4128,17 +4136,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl) Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl)
throws FHIRException, DefinitionException { throws FHIRException, DefinitionException {
List<String> profiles = new ArrayList<String>();
if (ei.definition != null) { if (ei.definition != null) {
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei,
extensionUrl, ei.definition, false);
}
if (ei.slice != null) {
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei,
extensionUrl, ei.slice, true);
}
}
public void checkChildByDefinition(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile,
ElementDefinition definition, Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept,
boolean checkDisplayInContext, ElementInfo ei, String extensionUrl, ElementDefinition checkDefn, boolean isSlice) {
List<String> profiles = new ArrayList<String>();
String type = null; String type = null;
ElementDefinition typeDefn = null; ElementDefinition typeDefn = null;
checkMustSupport(profile, ei); checkMustSupport(profile, ei);
if (ei.definition.getType().size() == 1 && !"*".equals(ei.definition.getType().get(0).getWorkingCode()) && !"Element".equals(ei.definition.getType().get(0).getWorkingCode()) if (checkDefn.getType().size() == 1 && !"*".equals(checkDefn.getType().get(0).getWorkingCode()) && !"Element".equals(checkDefn.getType().get(0).getWorkingCode())
&& !"BackboneElement".equals(ei.definition.getType().get(0).getWorkingCode())) { && !"BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode())) {
type = ei.definition.getType().get(0).getWorkingCode(); type = checkDefn.getType().get(0).getWorkingCode();
String stype = ei.getElement().fhirType(); String stype = ei.getElement().fhirType();
if (ei.definition.isChoice() && !stype.equals(type)) { if (checkDefn.isChoice() && !stype.equals(type)) {
if ("Extension".equals(profile.getType())) { if ("Extension".equals(profile.getType())) {
// error will be raised elsewhere // error will be raised elsewhere
} else { } else {
@ -4147,32 +4167,32 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
// //
// Excluding reference is a kludge to get around versioning issues // Excluding reference is a kludge to get around versioning issues
if (ei.definition.getType().get(0).hasProfile()) { if (checkDefn.getType().get(0).hasProfile()) {
for (CanonicalType p : ei.definition.getType().get(0).getProfile()) { for (CanonicalType p : checkDefn.getType().get(0).getProfile()) {
profiles.add(p.getValue()); profiles.add(p.getValue());
} }
} }
} else if (ei.definition.getType().size() == 1 && "*".equals(ei.definition.getType().get(0).getWorkingCode())) { } else if (checkDefn.getType().size() == 1 && "*".equals(checkDefn.getType().get(0).getWorkingCode())) {
String prefix = tail(ei.definition.getPath()); String prefix = tail(checkDefn.getPath());
assert prefix.endsWith("[x]"); assert prefix.endsWith("[x]");
type = ei.getName().substring(prefix.length() - 3); type = ei.getName().substring(prefix.length() - 3);
if (isPrimitiveType(type)) if (isPrimitiveType(type))
type = Utilities.uncapitalize(type); type = Utilities.uncapitalize(type);
if (ei.definition.getType().get(0).hasProfile()) { if (checkDefn.getType().get(0).hasProfile()) {
for (CanonicalType p : ei.definition.getType().get(0).getProfile()) { for (CanonicalType p : checkDefn.getType().get(0).getProfile()) {
profiles.add(p.getValue()); profiles.add(p.getValue());
} }
} }
} else if (ei.definition.getType().size() > 1) { } else if (checkDefn.getType().size() > 1) {
String prefix = tail(ei.definition.getPath()); String prefix = tail(checkDefn.getPath());
assert typesAreAllReference(ei.definition.getType()) || ei.definition.hasRepresentation(PropertyRepresentation.TYPEATTR) || prefix.endsWith("[x]") : prefix; assert typesAreAllReference(checkDefn.getType()) || checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR) || prefix.endsWith("[x]") : prefix;
if (ei.definition.hasRepresentation(PropertyRepresentation.TYPEATTR)) if (checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR))
type = ei.getElement().getType(); type = ei.getElement().getType();
else { else {
prefix = prefix.substring(0, prefix.length() - 3); prefix = prefix.substring(0, prefix.length() - 3);
for (TypeRefComponent t : ei.definition.getType()) for (TypeRefComponent t : checkDefn.getType())
if ((prefix + Utilities.capitalize(t.getWorkingCode())).equals(ei.getName())) { if ((prefix + Utilities.capitalize(t.getWorkingCode())).equals(ei.getName())) {
type = t.getWorkingCode(); type = t.getWorkingCode();
// Excluding reference is a kludge to get around versioning issues // Excluding reference is a kludge to get around versioning issues
@ -4181,18 +4201,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
if (type == null) { if (type == null) {
TypeRefComponent trc = ei.definition.getType().get(0); TypeRefComponent trc = checkDefn.getType().get(0);
if (trc.getWorkingCode().equals("Reference")) if (trc.getWorkingCode().equals("Reference"))
type = "Reference"; type = "Reference";
else else
rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTYPE, ei.getName(), describeTypes(ei.definition.getType())); rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTYPE, ei.getName(), describeTypes(checkDefn.getType()));
} }
} else if (ei.definition.getContentReference() != null) { } else if (checkDefn.getContentReference() != null) {
typeDefn = resolveNameReference(profile.getSnapshot(), ei.definition.getContentReference()); typeDefn = resolveNameReference(profile.getSnapshot(), checkDefn.getContentReference());
} else if (ei.definition.getType().size() == 1 && ("Element".equals(ei.definition.getType().get(0).getWorkingCode()) || "BackboneElement".equals(ei.definition.getType().get(0).getWorkingCode()))) { } else if (checkDefn.getType().size() == 1 && ("Element".equals(checkDefn.getType().get(0).getWorkingCode()) || "BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode()))) {
if (ei.definition.getType().get(0).hasProfile()) { if (checkDefn.getType().get(0).hasProfile()) {
CanonicalType pu = ei.definition.getType().get(0).getProfile().get(0); CanonicalType pu = checkDefn.getType().get(0).getProfile().get(0);
if (pu.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT)) if (pu.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT))
profiles.add(pu.getValue() + "#" + pu.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT)); profiles.add(pu.getValue() + "#" + pu.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT));
else else
@ -4202,11 +4222,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (type != null) { if (type != null) {
if (type.startsWith("@")) { if (type.startsWith("@")) {
ei.definition = findElement(profile, type.substring(1)); checkDefn = findElement(profile, type.substring(1));
if (isSlice) {
ei.slice = ei.definition;
} else {
ei.definition = ei.definition;
}
type = null; type = null;
} }
} }
NodeStack localStack = stack.push(ei.getElement(), ei.count, ei.definition, type == null ? typeDefn : resolveType(type, ei.definition.getType())); NodeStack localStack = stack.push(ei.getElement(), ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
// if (debug) { // if (debug) {
// System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl()); // System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl());
// } // }
@ -4217,34 +4242,34 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String thisExtension = null; String thisExtension = null;
boolean checkDisplay = true; boolean checkDisplay = true;
checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : ei.definition, resource, ei.getElement(), localStack, true); checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, resource, ei.getElement(), localStack, true);
ei.getElement().markValidation(profile, ei.definition); ei.getElement().markValidation(profile, checkDefn);
boolean elementValidated = false; boolean elementValidated = false;
if (type != null) { if (type != null) {
if (isPrimitiveType(type)) { if (isPrimitiveType(type)) {
checkPrimitive(hostContext, errors, ei.getPath(), type, ei.definition, ei.getElement(), profile, stack); checkPrimitive(hostContext, errors, ei.getPath(), type, checkDefn, ei.getElement(), profile, stack);
} else { } else {
if (ei.definition.hasFixed()) { if (checkDefn.hasFixed()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), ei.definition.getFixed(), profile.getUrl(), ei.definition.getSliceName(), null); checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getUrl(), checkDefn.getSliceName(), null);
} }
if (ei.definition.hasPattern()) { if (checkDefn.hasPattern()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), ei.definition.getPattern(), profile.getUrl(), ei.definition.getSliceName(), null, true); checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getPattern(), profile.getUrl(), checkDefn.getSliceName(), null, true);
} }
} }
if (type.equals("Identifier")) { if (type.equals("Identifier")) {
checkIdentifier(errors, ei.getPath(), ei.getElement(), ei.definition); checkIdentifier(errors, ei.getPath(), ei.getElement(), checkDefn);
} else if (type.equals("Coding")) { } else if (type.equals("Coding")) {
checkCoding(errors, ei.getPath(), ei.getElement(), profile, ei.definition, inCodeableConcept, checkDisplayInContext, stack); checkCoding(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack);
} else if (type.equals("Quantity")) { } else if (type.equals("Quantity")) {
checkQuantity(errors, ei.getPath(), ei.getElement(), profile, ei.definition, stack); checkQuantity(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack);
} else if (type.equals("Attachment")) { } else if (type.equals("Attachment")) {
checkAttachment(errors, ei.getPath(), ei.getElement(), profile, ei.definition, inCodeableConcept, checkDisplayInContext, stack); checkAttachment(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack);
} else if (type.equals("CodeableConcept")) { } else if (type.equals("CodeableConcept")) {
checkDisplay = checkCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, ei.definition, stack); checkDisplay = checkCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack);
thisIsCodeableConcept = true; thisIsCodeableConcept = true;
} else if (type.equals("Reference")) { } else if (type.equals("Reference")) {
checkReference(hostContext, errors, ei.getPath(), ei.getElement(), profile, ei.definition, actualType, localStack); checkReference(hostContext, errors, ei.getPath(), ei.getElement(), profile, checkDefn, actualType, localStack);
// We only check extensions if we're not in a complex extension or if the element we're dealing with is not defined as part of that complex extension // We only check extensions if we're not in a complex extension or if the element we're dealing with is not defined as part of that complex extension
} else if (type.equals("Extension")) { } else if (type.equals("Extension")) {
Element eurl = ei.getElement().getNamedChild("url"); Element eurl = ei.getElement().getNamedChild("url");
@ -4253,12 +4278,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
thisExtension = url; thisExtension = url;
if (rule(errors, IssueType.INVALID, ei.getPath(), !Utilities.noString(url), I18nConstants.EXTENSION_EXT_URL_NOTFOUND)) { if (rule(errors, IssueType.INVALID, ei.getPath(), !Utilities.noString(url), I18nConstants.EXTENSION_EXT_URL_NOTFOUND)) {
if (rule(errors, IssueType.INVALID, ei.getPath(), (extensionUrl != null) || Utilities.isAbsoluteUrl(url), I18nConstants.EXTENSION_EXT_URL_ABSOLUTE)) { if (rule(errors, IssueType.INVALID, ei.getPath(), (extensionUrl != null) || Utilities.isAbsoluteUrl(url), I18nConstants.EXTENSION_EXT_URL_ABSOLUTE)) {
checkExtension(hostContext, errors, ei.getPath(), resource, element, ei.getElement(), ei.definition, profile, localStack, stack, extensionUrl); checkExtension(hostContext, errors, ei.getPath(), resource, element, ei.getElement(), checkDefn, profile, localStack, stack, extensionUrl);
} }
} }
} }
} else if (type.equals("Resource") || isResource(type)) { } else if (type.equals("Resource") || isResource(type)) {
validateContains(hostContext, errors, ei.getPath(), ei.definition, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei)); // if validateContains(hostContext, errors, ei.getPath(), checkDefn, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei)); // if
elementValidated = true; elementValidated = true;
// (str.matches(".*([.,/])work\\1$")) // (str.matches(".*([.,/])work\\1$"))
} else if (Utilities.isAbsoluteUrl(type)) { } else if (Utilities.isAbsoluteUrl(type)) {
@ -4266,22 +4291,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (defn != null && hasMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep())) { if (defn != null && hasMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep())) {
List<String> txtype = getMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep()); List<String> txtype = getMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep());
if (txtype.contains("CodeableConcept")) { if (txtype.contains("CodeableConcept")) {
checkTerminologyCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, ei.definition, stack, defn); checkTerminologyCodeableConcept(errors, ei.getPath(), ei.getElement(), profile, checkDefn, stack, defn);
thisIsCodeableConcept = true; thisIsCodeableConcept = true;
} else if (txtype.contains("Coding")) { } else if (txtype.contains("Coding")) {
checkTerminologyCoding(errors, ei.getPath(), ei.getElement(), profile, ei.definition, inCodeableConcept, checkDisplayInContext, stack, defn); checkTerminologyCoding(errors, ei.getPath(), ei.getElement(), profile, checkDefn, inCodeableConcept, checkDisplayInContext, stack, defn);
} }
} }
} }
} else { } else {
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), ei.definition != null, I18nConstants.VALIDATION_VAL_CONTENT_UNKNOWN, ei.getName())) if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), checkDefn != null, I18nConstants.VALIDATION_VAL_CONTENT_UNKNOWN, ei.getName()))
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.getElement(), type, localStack, false, true, null); validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, false, true, null);
} }
StructureDefinition p = null; StructureDefinition p = null;
String tail = null; String tail = null;
if (profiles.isEmpty()) { if (profiles.isEmpty()) {
if (type != null) { if (type != null) {
p = getProfileForType(type, ei.definition.getType()); p = getProfileForType(type, checkDefn.getType());
// If dealing with a primitive type, then we need to check the current child against // If dealing with a primitive type, then we need to check the current child against
// the invariants (constraints) on the current element, because otherwise it only gets // the invariants (constraints) on the current element, because otherwise it only gets
@ -4314,7 +4339,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
p = this.context.fetchResource(StructureDefinition.class, typeProfile); p = this.context.fetchResource(StructureDefinition.class, typeProfile);
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, typeProfile)) { if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, typeProfile)) {
List<ValidationMessage> profileErrors = new ArrayList<ValidationMessage>(); List<ValidationMessage> profileErrors = new ArrayList<ValidationMessage>();
validateElement(hostContext, profileErrors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, profileErrors, p, getElementByTail(p, tail), profile, checkDefn, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
if (hasErrors(profileErrors)) if (hasErrors(profileErrors))
badProfiles.put(typeProfile, profileErrors); badProfiles.put(typeProfile, profileErrors);
else else
@ -4348,16 +4373,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (!elementValidated) { if (!elementValidated) {
if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER) if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER)
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, ei.getElement(), ei.getElement(), type, localStack.resetIds(), thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, checkDefn, ei.getElement(), ei.getElement(), type, localStack.resetIds(), thisIsCodeableConcept, checkDisplay, thisExtension);
else else
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, checkDefn, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
} }
int index = profile.getSnapshot().getElement().indexOf(ei.definition); int index = profile.getSnapshot().getElement().indexOf(checkDefn);
if (index < profile.getSnapshot().getElement().size() - 1) { if (index < profile.getSnapshot().getElement().size() - 1) {
String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath(); String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath();
if (!nextPath.equals(ei.definition.getPath()) && nextPath.startsWith(ei.definition.getPath())) if (!nextPath.equals(checkDefn.getPath()) && nextPath.startsWith(checkDefn.getPath()))
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
}
} }
} }
} }
@ -5091,4 +5115,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return questionnaireMode; return questionnaireMode;
} }
public boolean isWantCheckSnapshotUnchanged() {
return wantCheckSnapshotUnchanged;
}
public void setWantCheckSnapshotUnchanged(boolean wantCheckSnapshotUnchanged) {
this.wantCheckSnapshotUnchanged = wantCheckSnapshotUnchanged;
}
} }