Add new validation for must-support on types / profiles / targets + improve extension validation
This commit is contained in:
parent
c2fb9e8fd3
commit
73d5a845bf
|
@ -341,6 +341,8 @@ public class I18nConstants {
|
|||
public static final String RESOURCE_TYPE_MISMATCH_FOR___ = "Resource_type_mismatch_for___";
|
||||
public static final String SAME_ID_ON_MULTIPLE_ELEMENTS__IN_ = "Same_id_on_multiple_elements__in_";
|
||||
public static final String SD_MUST_HAVE_DERIVATION = "SD_MUST_HAVE_DERIVATION";
|
||||
public static final String SD_NESTED_MUST_SUPPORT_DIFF = "SD_NESTED_MUST_SUPPORT_DIFF";
|
||||
public static final String SD_NESTED_MUST_SUPPORT_SNAPSHOT = "SD_NESTED_MUST_SUPPORT_SNAPSHOT";
|
||||
public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG";
|
||||
public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG";
|
||||
public static final String SEARCHPARAMETER_NOTFOUND = "SEARCHPARAMETER_NOTFOUND";
|
||||
|
|
|
@ -608,4 +608,7 @@ REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect,
|
|||
TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable
|
||||
XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'')
|
||||
UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported property {3} on type {2} for pattern for discriminator({0}) for slice {1}
|
||||
UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator({0}) for slice {1}
|
||||
UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator({0}) for slice {1}
|
||||
SD_NESTED_MUST_SUPPORT_DIFF = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support. The inner must-supports will be ignored unless the element inherits must-support = true
|
||||
SD_NESTED_MUST_SUPPORT_SNAPSHOT = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support
|
||||
|
|
@ -296,9 +296,10 @@ public class BaseValidator {
|
|||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
|
||||
protected boolean hint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null);
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, null);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
private boolean isKnownExtension(String url) {
|
||||
// Added structuredefinition-expression and following extensions explicitly because they weren't defined in the version of the spec they need to be used with
|
||||
if ((allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression") || url.equals(VersionConvertorConstants.IG_DEPENDSON_PACKAGE_EXTENSION))
|
||||
if ((allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression"))
|
||||
return true;
|
||||
for (String s : extensionDomains)
|
||||
if (url.startsWith(s))
|
||||
|
@ -1521,6 +1521,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (extensionUrl.equals(profile.getUrl())) {
|
||||
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", hasExtensionSlice(profile, url), I18nConstants.EXTENSION_EXT_SUBEXTENSION_INVALID, url, profile.getUrl());
|
||||
}
|
||||
} else if (SpecialExtensions.isKnownExtension(url)) {
|
||||
ex = SpecialExtensions.getDefinition(url);
|
||||
} else if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowUnknownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN_NOTHERE, url)) {
|
||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, isKnownExtension(url), I18nConstants.EXTENSION_EXT_UNKNOWN, url);
|
||||
}
|
||||
|
@ -1556,6 +1558,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return ex;
|
||||
}
|
||||
|
||||
|
||||
private boolean hasExtensionSlice(StructureDefinition profile, String sliceName) {
|
||||
for (ElementDefinition ed : profile.getSnapshot().getElement()) {
|
||||
if (ed.getPath().equals("Extension.extension.url") && ed.hasFixed() && sliceName.equals(ed.getFixed().primitiveValue())) {
|
||||
|
@ -1933,7 +1936,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (fetcher != null) {
|
||||
boolean found;
|
||||
try {
|
||||
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (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.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url) ||
|
||||
SpecialExtensions.isKnownExtension(url);
|
||||
} catch (IOException e1) {
|
||||
found = false;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,6 +28,7 @@ import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
|||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
|
@ -95,6 +96,69 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
} catch (FHIRException | IOException e) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
|
||||
}
|
||||
List<Element> differentials = src.getChildrenByName("differential");
|
||||
List<Element> snapshots = src.getChildrenByName("snapshot");
|
||||
for (Element differential : differentials) {
|
||||
validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0);
|
||||
}
|
||||
for (Element snapshot : snapshots) {
|
||||
validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot) {
|
||||
List<Element> elements = elementList.getChildrenByName("element");
|
||||
int cc = 0;
|
||||
for (Element element : elements) {
|
||||
validateElementDefinition(errors, element, stack.push(element, cc, null, null), snapshot, hasSnapshot);
|
||||
cc++;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateElementDefinition(List<ValidationMessage> errors, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot) {
|
||||
boolean typeMustSupport = false;
|
||||
List<Element> types = element.getChildrenByName("type");
|
||||
for (Element type : types) {
|
||||
if (hasMustSupportExtension(type)) {
|
||||
typeMustSupport = true;
|
||||
}
|
||||
}
|
||||
if (typeMustSupport) {
|
||||
if (snapshot) {
|
||||
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_SNAPSHOT, element.getNamedChildValue("path"));
|
||||
} else {
|
||||
hint(errors, IssueType.EXCEPTION, stack.getLiteralPath(), hasSnapshot || "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_DIFF, element.getNamedChildValue("path"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasMustSupportExtension(Element type) {
|
||||
if ("true".equals(getExtensionValue(type, ToolingExtensions.EXT_MUST_SUPPORT))) {
|
||||
return true;
|
||||
}
|
||||
List<Element> profiles = type.getChildrenByName("profile");
|
||||
for (Element profile : profiles) {
|
||||
if ("true".equals(getExtensionValue(profile, ToolingExtensions.EXT_MUST_SUPPORT))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
profiles = type.getChildrenByName("targetProfile");
|
||||
for (Element profile : profiles) {
|
||||
if ("true".equals(getExtensionValue(profile, ToolingExtensions.EXT_MUST_SUPPORT))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getExtensionValue(Element element, String url) {
|
||||
List<Element> extensions = element.getChildrenByName("extension");
|
||||
for (Element extension : extensions) {
|
||||
if (url.equals(extension.getNamedChildValue("url"))) {
|
||||
return extension.getNamedChildValue("value");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private StructureDefinition loadAsSD(Element src) throws FHIRException, IOException {
|
||||
|
|
Loading…
Reference in New Issue