Merge branch 'master' into gg-20211-delayed-load
This commit is contained in:
commit
06d4ae483f
|
@ -1,8 +1,14 @@
|
||||||
Validator:
|
|
||||||
* no changes (yet)
|
Validator:
|
||||||
|
* enforce minValue and maxValue for decimal and Quantity types
|
||||||
Other code changes:
|
|
||||||
* remove relative URL prefixing
|
Other code changes:
|
||||||
* Add delayed load resources to all resources
|
* Fix trailing slashes for JAVA_HOME tests
|
||||||
* Don't load resources from core examples package over other resources
|
* remove relative URL prefixing
|
||||||
* Fix trailing slashes for JAVA_HOME tests
|
* Add delayed load resources to all resources
|
||||||
|
* Don't load resources from core examples package over other resources
|
||||||
|
* Fix count on erroneous element defintions when generating snapshots
|
||||||
|
* add version specific access to context resources
|
||||||
|
* fix error rendering lists with encounter references
|
||||||
|
* fix error rendering questionnaire answer lists
|
||||||
|
* improve rendering of version specific and targetted references
|
||||||
|
|
|
@ -691,8 +691,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
if (!e.hasUserData(GENERATED_IN_SNAPSHOT)) {
|
if (!e.hasUserData(GENERATED_IN_SNAPSHOT)) {
|
||||||
b.append(e.hasId() ? "id: "+e.getId() : "path: "+e.getPath());
|
b.append(e.hasId() ? "id: "+e.getId() : "path: "+e.getPath());
|
||||||
|
ce++;
|
||||||
if (e.hasId()) {
|
if (e.hasId()) {
|
||||||
ce++;
|
|
||||||
String msg = "No match found in the generated snapshot: check that the path and definitions are legal in the differential (including order)";
|
String msg = "No match found in the generated snapshot: check that the path and definitions are legal in the differential (including order)";
|
||||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+e.getId(), msg, ValidationMessage.IssueSeverity.ERROR));
|
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+e.getId(), msg, ValidationMessage.IssueSeverity.ERROR));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1279,8 +1279,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
return fetchResourceWithException(cls, uri, null);
|
return fetchResourceWithException(cls, uri, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, CanonicalResource source) throws FHIRException {
|
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, CanonicalResource source) throws FHIRException {
|
||||||
|
return fetchResourceWithException(class_, uri, null, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, String version, CanonicalResource source) throws FHIRException {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1294,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
|
||||||
String version = null;
|
|
||||||
if (uri.contains("|")) {
|
if (uri.contains("|")) {
|
||||||
version = uri.substring(uri.lastIndexOf("|")+1);
|
version = uri.substring(uri.lastIndexOf("|")+1);
|
||||||
uri = uri.substring(0, uri.lastIndexOf("|"));
|
uri = uri.substring(0, uri.lastIndexOf("|"));
|
||||||
|
@ -1338,10 +1341,23 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
if (questionnaires.has(uri)) {
|
if (questionnaires.has(uri)) {
|
||||||
return (T) questionnaires.get(uri, version);
|
return (T) questionnaires.get(uri, version);
|
||||||
}
|
}
|
||||||
|
if (uri.matches(Constants.URI_REGEX) && !uri.contains("ValueSet")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it might be a special URL.
|
||||||
|
if (Utilities.isAbsoluteUrl(uri) || uri.startsWith("ValueSet/")) {
|
||||||
|
Resource res = null; // findTxValueSet(uri);
|
||||||
|
if (res != null) {
|
||||||
|
return (T) res;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (Map<String, ResourceProxy> rt : allResourcesById.values()) {
|
for (Map<String, ResourceProxy> rt : allResourcesById.values()) {
|
||||||
for (ResourceProxy r : rt.values()) {
|
for (ResourceProxy r : rt.values()) {
|
||||||
if (uri.equals(r.getUrl())) {
|
if (uri.equals(r.getUrl())) {
|
||||||
return (T) r.getResource();
|
if (version == null || version == r.getResource().getMeta().getVersionId()) {
|
||||||
|
return (T) r.getResource();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1385,20 +1401,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
if (class_ == Questionnaire.class) {
|
if (class_ == Questionnaire.class) {
|
||||||
return (T) questionnaires.get(uri, version);
|
return (T) questionnaires.get(uri, version);
|
||||||
}
|
}
|
||||||
if (class_ == null) {
|
|
||||||
if (uri.matches(Constants.URI_REGEX) && !uri.contains("ValueSet")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it might be a special URL.
|
|
||||||
if (Utilities.isAbsoluteUrl(uri) || uri.startsWith("ValueSet/")) {
|
|
||||||
Resource res = null; // findTxValueSet(uri);
|
|
||||||
if (res != null) {
|
|
||||||
return (T) res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (supportedCodeSystems.contains(uri)) {
|
if (supportedCodeSystems.contains(uri)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1635,6 +1637,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version) {
|
||||||
|
try {
|
||||||
|
return fetchResourceWithException(class_, uri, version, null);
|
||||||
|
} catch (FHIRException e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Resource> boolean hasResource(Class<T> class_, String uri) {
|
public <T extends Resource> boolean hasResource(Class<T> class_, String uri) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -337,6 +337,7 @@ public interface IWorkerContext {
|
||||||
*/
|
*/
|
||||||
public <T extends Resource> T fetchResource(Class<T> class_, String uri);
|
public <T extends Resource> T fetchResource(Class<T> class_, String uri);
|
||||||
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
|
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
|
||||||
|
public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version);
|
||||||
|
|
||||||
/** has the same functionality as fetchResource, but passes in information about the source of the
|
/** has the same functionality as fetchResource, but passes in information about the source of the
|
||||||
* reference (this may affect resolution of version)
|
* reference (this may affect resolution of version)
|
||||||
|
|
|
@ -59,7 +59,8 @@ public class ListRenderer extends ResourceRenderer {
|
||||||
shortForRef(td, list.get("subject"));
|
shortForRef(td, list.get("subject"));
|
||||||
}
|
}
|
||||||
if (list.has("encounter")) {
|
if (list.has("encounter")) {
|
||||||
shortForRef(td.tx("Encounter: "), list.get("encounter"));
|
td.tx("Encounter: ");
|
||||||
|
shortForRef(td, list.get("encounter"));
|
||||||
}
|
}
|
||||||
if (list.has("source")) {
|
if (list.has("source")) {
|
||||||
td.tx("Source: ");
|
td.tx("Source: ");
|
||||||
|
|
|
@ -703,7 +703,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
if (i.hasAnswerValueSet()) {
|
if (i.hasAnswerValueSet()) {
|
||||||
XhtmlNode ans = item(ul, "Answers");
|
XhtmlNode ans = item(ul, "Answers");
|
||||||
if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
|
if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
|
||||||
ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
|
ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
|
||||||
if (vs == null) {
|
if (vs == null) {
|
||||||
ans.tx(i.getAnswerValueSet());
|
ans.tx(i.getAnswerValueSet());
|
||||||
|
|
|
@ -202,7 +202,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
}
|
}
|
||||||
// what to display: if text is provided, then that. if the reference was resolved, then show the name, or the generated narrative
|
// what to display: if text is provided, then that. if the reference was resolved, then show the name, or the generated narrative
|
||||||
String display = r.hasDisplayElement() ? r.getDisplay() : null;
|
String display = r.hasDisplayElement() ? r.getDisplay() : null;
|
||||||
String name = tr != null && tr.getResource() != null ? tr.getResource().getNameFromResource() : null;
|
String name = tr != null && tr.getResource() != null ? tr.getResource().getNameFromResource() : null;
|
||||||
|
|
||||||
if (display == null && (tr == null || tr.getResource() == null)) {
|
if (display == null && (tr == null || tr.getResource() == null)) {
|
||||||
c.addText(r.getReference());
|
c.addText(r.getReference());
|
||||||
|
@ -214,6 +214,11 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
if ((tr == null || !tr.getReference().startsWith("#")) && name != null) {
|
if ((tr == null || !tr.getReference().startsWith("#")) && name != null) {
|
||||||
x.addText(" \""+name+"\"");
|
x.addText(" \""+name+"\"");
|
||||||
}
|
}
|
||||||
|
if (r.hasExtension(ToolingExtensions.EXT_TARGET_ID)) {
|
||||||
|
x.addText("(#"+r.getExtensionString(ToolingExtensions.EXT_TARGET_ID)+")");
|
||||||
|
} else if (r.hasExtension(ToolingExtensions.EXT_TARGET_PATH)) {
|
||||||
|
x.addText("(#/"+r.getExtensionString(ToolingExtensions.EXT_TARGET_PATH)+")");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (display != null) {
|
if (display != null) {
|
||||||
c.addText(display);
|
c.addText(display);
|
||||||
|
@ -272,6 +277,11 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String version = null;
|
||||||
|
if (url.contains("/_history/")) {
|
||||||
|
version = url.substring(url.indexOf("/_history/")+10);
|
||||||
|
url = url.substring(0, url.indexOf("/_history/"));
|
||||||
|
}
|
||||||
|
|
||||||
if (rcontext != null) {
|
if (rcontext != null) {
|
||||||
BundleEntryComponent bundleResource = rcontext.resolve(url);
|
BundleEntryComponent bundleResource = rcontext.resolve(url);
|
||||||
|
@ -279,7 +289,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + bundleResource.getResource().getId();
|
String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + bundleResource.getResource().getId();
|
||||||
return new ResourceWithReference(bundleUrl, new ResourceWrapperDirect(this.context, bundleResource.getResource()));
|
return new ResourceWithReference(bundleUrl, new ResourceWrapperDirect(this.context, bundleResource.getResource()));
|
||||||
}
|
}
|
||||||
org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url);
|
org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url, version);
|
||||||
if (bundleElement != null) {
|
if (bundleElement != null) {
|
||||||
String bundleUrl = null;
|
String bundleUrl = null;
|
||||||
Element br = bundleElement.getNamedChild("resource");
|
Element br = bundleElement.getNamedChild("resource");
|
||||||
|
@ -292,7 +302,7 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource ae = getContext().getWorker().fetchResource(null, url);
|
Resource ae = getContext().getWorker().fetchResource(null, url, version);
|
||||||
if (ae != null)
|
if (ae != null)
|
||||||
return new ResourceWithReference(url, new ResourceWrapperDirect(this.context, ae));
|
return new ResourceWithReference(url, new ResourceWrapperDirect(this.context, ae));
|
||||||
else if (context.getResolver() != null) {
|
else if (context.getResolver() != null) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class Resolver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value) {
|
public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value, String version) {
|
||||||
if (value.startsWith("#")) {
|
if (value.startsWith("#")) {
|
||||||
if (resourceElement != null) {
|
if (resourceElement != null) {
|
||||||
for (org.hl7.fhir.r5.elementmodel.Element r : resourceElement.getChildrenByName("contained")) {
|
for (org.hl7.fhir.r5.elementmodel.Element r : resourceElement.getChildrenByName("contained")) {
|
||||||
|
@ -115,10 +115,18 @@ public class Resolver {
|
||||||
if (containerElement != null) {
|
if (containerElement != null) {
|
||||||
for (org.hl7.fhir.r5.elementmodel.Element be : containerElement.getChildren("entry")) {
|
for (org.hl7.fhir.r5.elementmodel.Element be : containerElement.getChildren("entry")) {
|
||||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||||
if (value.equals(be.getChildValue("fullUrl")))
|
if (res != null) {
|
||||||
return be;
|
if (value.equals(be.getChildValue("fullUrl"))) {
|
||||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
if (checkVersion(version, res)) {
|
||||||
return be;
|
return be;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.equals(res.fhirType()+"/"+res.getChildValue("id"))) {
|
||||||
|
if (checkVersion(version, res)) {
|
||||||
|
return be;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,13 +134,27 @@ public class Resolver {
|
||||||
if (containerElement != null) {
|
if (containerElement != null) {
|
||||||
for (org.hl7.fhir.r5.elementmodel.Element p : containerElement.getChildren("parameter")) {
|
for (org.hl7.fhir.r5.elementmodel.Element p : containerElement.getChildren("parameter")) {
|
||||||
org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource");
|
org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource");
|
||||||
if (res != null && value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
if (res != null && value.equals(res.fhirType()+"/"+res.getChildValue("id"))) {
|
||||||
return p;
|
if (checkVersion(version, res)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkVersion(String version, org.hl7.fhir.r5.elementmodel.Element res) {
|
||||||
|
if (version == null) {
|
||||||
|
return true;
|
||||||
|
} else if (!res.hasChild("meta")) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
org.hl7.fhir.r5.elementmodel.Element meta = res.getNamedChild("meta");
|
||||||
|
return version.equals(meta.getChildValue("version"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResourceWithReference {
|
public static class ResourceWithReference {
|
||||||
|
|
|
@ -5539,7 +5539,7 @@ public class FHIRPathEngine {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_NAME, expr.getName());
|
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_NAME, expr.getName());
|
||||||
}
|
}
|
||||||
} else if (expr.getKind() == Kind.Group) {
|
} else if (expr.getKind() == Kind.Group) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP);
|
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP, expr.toString());
|
||||||
} else if (expr.getKind() == Kind.Constant) {
|
} else if (expr.getKind() == Kind.Constant) {
|
||||||
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST);
|
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST);
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,8 @@ public class ToolingExtensions {
|
||||||
public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name";
|
public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name";
|
||||||
public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-style";
|
public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-style";
|
||||||
public static final String EXT_BINARY_FORMAT = "http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format";
|
public static final String EXT_BINARY_FORMAT = "http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format";
|
||||||
|
public static final String EXT_TARGET_ID = "http://hl7.org/fhir/StructureDefinition/targetElement";
|
||||||
|
public static final String EXT_TARGET_PATH = "http://hl7.org/fhir/StructureDefinition/targetPath";
|
||||||
|
|
||||||
// specific extension helpers
|
// specific extension helpers
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.hl7.fhir.utilities.i18n;
|
package org.hl7.fhir.utilities.i18n;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
|
|
||||||
public class I18nConstants {
|
public class I18nConstants {
|
||||||
|
@ -483,6 +484,8 @@ public class I18nConstants {
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS = "TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS = "TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_RANGE = "Type_Specific_Checks_DT_Decimal_Range";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_RANGE = "Type_Specific_Checks_DT_Decimal_Range";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_VALID = "Type_Specific_Checks_DT_Decimal_Valid";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_VALID = "Type_Specific_Checks_DT_Decimal_Valid";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_GT = "Type_Specific_Checks_DT_Decimal_GT";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_DECIMAL_LT = "Type_Specific_Checks_DT_Decimal_LT";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE = "TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE = "TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM = "Type_Specific_Checks_DT_Identifier_System";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM = "Type_Specific_Checks_DT_Identifier_System";
|
||||||
public static final String TYPE_SPECIFIC_CHECKS_DT_ID_VALID = "Type_Specific_Checks_DT_ID_Valid";
|
public static final String TYPE_SPECIFIC_CHECKS_DT_ID_VALID = "Type_Specific_Checks_DT_ID_Valid";
|
||||||
|
@ -659,6 +662,35 @@ public class I18nConstants {
|
||||||
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL";
|
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL";
|
||||||
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG";
|
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG";
|
||||||
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING";
|
public static final String CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING = "CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_QTY = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_QTY";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_SYSTEM_MISMATCH = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_SYSTEM_MISMATCH";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_CODE_MISMATCH = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_CODE_MISMATCH";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_VALUE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_VALUE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_VALUE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_VALUE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_SYSTEM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_SYSTEM";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_SYSTEM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_SYSTEM";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CODE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CODE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_CODE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_CODE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_UCUM_SVC = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_UCUM_SVC";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CONVERT = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CONVERT";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG_UCUM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG_UCUM";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_QTY = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_QTY";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_SYSTEM_MISMATCH = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_SYSTEM_MISMATCH";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_CODE_MISMATCH = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_CODE_MISMATCH";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_VALUE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_VALUE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_VALUE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_VALUE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_SYSTEM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_SYSTEM";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_SYSTEM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_SYSTEM";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CODE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CODE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_CODE = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_CODE";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_UCUM_SVC = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_UCUM_SVC";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CONVERT = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CONVERT";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG";
|
||||||
|
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM = "TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,8 @@ Type_Specific_Checks_DT_DateTime_Valid = Not a valid date/time ({0})
|
||||||
Type_Specific_Checks_DT_Date_Valid = Not a valid date ({0})
|
Type_Specific_Checks_DT_Date_Valid = Not a valid date ({0})
|
||||||
Type_Specific_Checks_DT_Decimal_Range = The value ''{0}'' is outside the range of commonly/reasonably supported decimals
|
Type_Specific_Checks_DT_Decimal_Range = The value ''{0}'' is outside the range of commonly/reasonably supported decimals
|
||||||
Type_Specific_Checks_DT_Decimal_Valid = The value ''{0}'' is not a valid decimal
|
Type_Specific_Checks_DT_Decimal_Valid = The value ''{0}'' is not a valid decimal
|
||||||
|
Type_Specific_Checks_DT_Decimal_GT = value is greater than permitted maximum value of {0}
|
||||||
|
Type_Specific_Checks_DT_Decimal_LT = value is less than permitted minimum value of {0}
|
||||||
Type_Specific_Checks_DT_ID_Valid = id value ''{0}'' is not valid
|
Type_Specific_Checks_DT_ID_Valid = id value ''{0}'' is not valid
|
||||||
Type_Specific_Checks_DT_Identifier_System = Identifier.system must be an absolute reference, not a local reference
|
Type_Specific_Checks_DT_Identifier_System = Identifier.system must be an absolute reference, not a local reference
|
||||||
Type_Specific_Checks_DT_Instant_Valid = Not a valid instant ({0})
|
Type_Specific_Checks_DT_Instant_Valid = Not a valid instant ({0})
|
||||||
|
@ -571,7 +573,7 @@ FHIRPATH_DISCRIMINATOR_TYPE_NONE = illegal use of ofType() in discriminator - no
|
||||||
FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE = illegal use of ofType() in discriminator - Multiple possible types on {0}
|
FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE = illegal use of ofType() in discriminator - Multiple possible types on {0}
|
||||||
FHIRPATH_DISCRIMINATOR_NO_CODE = illegal use of ofType() in discriminator - Type has no code on {0}
|
FHIRPATH_DISCRIMINATOR_NO_CODE = illegal use of ofType() in discriminator - Type has no code on {0}
|
||||||
FHIRPATH_DISCRIMINATOR_BAD_NAME = illegal function name {0}() in discriminator
|
FHIRPATH_DISCRIMINATOR_BAD_NAME = illegal function name {0}() in discriminator
|
||||||
FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP = illegal expression syntax in discriminator (group)
|
FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_GROUP = illegal expression syntax in discriminator (group ''{0}'')
|
||||||
FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST = illegal expression syntax in discriminator (const)
|
FHIRPATH_DISCRIMINATOR_BAD_SYNTAX_CONST = illegal expression syntax in discriminator (const)
|
||||||
FHIRPATH_DISCRIMINATOR_CANT_FIND = Unable to resolve discriminator in definitions: {0} in profile {1} on element {2}, looking in profile {3}
|
FHIRPATH_DISCRIMINATOR_CANT_FIND = Unable to resolve discriminator in definitions: {0} in profile {1} on element {2}, looking in profile {3}
|
||||||
FHIRPATH_DISCRIMINATOR_CANT_FIND_EXTENSION = Unable to resolve discriminator {0} on {2} found in the definitions because the extension {1} wasn''t found in the profile {3}
|
FHIRPATH_DISCRIMINATOR_CANT_FIND_EXTENSION = Unable to resolve discriminator {0} on {2} found in the definitions because the extension {1} wasn''t found in the profile {3}
|
||||||
|
@ -670,4 +672,30 @@ CODESYSTEM_CS_NONHL7_MISSING_ELEMENT = CodeSystems SHOULD have a stated value fo
|
||||||
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL = CodeSystems SHOULD NOT have a stated value for the {0} element when they are a supplement
|
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL = CodeSystems SHOULD NOT have a stated value for the {0} element when they are a supplement
|
||||||
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG = CodeSystem Supplements SHALL have a content value of 'supplement'
|
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG = CodeSystem Supplements SHALL have a content value of 'supplement'
|
||||||
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING = CodeSystem Supplements with a content value of 'supplement' SHALL have a supplements elemnet that specifies which code system is being supplemented
|
CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING = CodeSystem Supplements with a content value of 'supplement' SHALL have a supplements elemnet that specifies which code system is being supplemented
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_QTY = Found {0} of type {2} in the profile validating a Quantity (so it must be a Quantity)
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_SYSTEM_MISMATCH = The minValue in the profile has a system of {0} which is different to the system in the value {1} so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_CODE_MISMATCH = The minValue in the profile has a system code of {0} which is different to the system code in the value {1} so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_VALUE = The minValue in the profile doesn't have an actual value, so the minimum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_VALUE = The quantity doesn't have an actual value, so the minimum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_SYSTEM = The minValue in the profile has no system so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_SYSTEM = The value has no system so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CODE = The minValue in the profile has no code so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_CODE = The value has no code so the minimum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_UCUM_SVC = There is no UCUM service, and the UCUM codes aren't identical, so the minimum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CONVERT = Unable to convert value {0} from unit {1} to minValue unit {2} based on UCUM definitions; minimum value is not valid
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG = The value in the instance ({2}) is less than the specified minimum value ({3})
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG_UCUM = The value in the instance ({0} {1}) is less than the specified minValue ({2} {3}) after UCUM conversion
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_QTY = Found {0} of type {2} in the profile validating a Quantity (so it must be a Quantity)
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_SYSTEM_MISMATCH = The maxValue in the profile has a system of {0} which is different to the system in the value {1} so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_CODE_MISMATCH = The maxValue in the profile has a system code of {0} which is different to the system code in the value {1} so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_VALUE = The maxValue in the profile doesn't have an actual value, so the maximum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_VALUE = The quantity doesn't have an actual value, so the maximum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_SYSTEM = The maxValue in the profile has no system so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_SYSTEM = The value has no system so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CODE = The maxValue in the profile has no code so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_CODE = The value has no code so the maximum value cannot be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_UCUM_SVC = There is no UCUM service, and the UCUM codes aren't identical, so the maximum value can't be checked
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CONVERT = Unable to convert value {0} from unit {1} to maxValue unit {2} based on UCUM definitions; maximum value is not valid
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG = The value in the instance ({2}) is greater than the specified maximum value ({3})
|
||||||
|
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM = The value in the instance ({0} {1}) is greater than the specified maxValue ({2} {3}) after UCUM conversion
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ package org.hl7.fhir.validation;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import org.fhir.ucum.UcumEssenceService;
|
||||||
|
import org.fhir.ucum.UcumException;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||||
|
@ -227,6 +230,15 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
||||||
context = SimpleWorkerContext.fromDefinitions(source, ValidatorUtils.loaderForVersion(version), new PackageVersion(src));
|
context = SimpleWorkerContext.fromDefinitions(source, ValidatorUtils.loaderForVersion(version), new PackageVersion(src));
|
||||||
ValidatorUtils.grabNatives(getBinaries(), source, "http://hl7.org/fhir");
|
ValidatorUtils.grabNatives(getBinaries(), source, "http://hl7.org/fhir");
|
||||||
}
|
}
|
||||||
|
// ucum-essence.xml should be in the class path. if it's not, ask about how to sort this out
|
||||||
|
// on https://chat.fhir.org/#narrow/stream/179167-hapi
|
||||||
|
try {
|
||||||
|
ClassLoader classLoader = ValidationEngine.class.getClassLoader();
|
||||||
|
InputStream ue = classLoader.getResourceAsStream("ucum-essence.xml");
|
||||||
|
context.setUcumService(new UcumEssenceService(ue));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new FHIRException("Error loading UCUM from embedded ucum-essence.xml: "+e.getMessage(), e);
|
||||||
|
}
|
||||||
initContext(tt);
|
initContext(tt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ 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.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
@ -51,6 +52,7 @@ import java.util.UUID;
|
||||||
import org.apache.commons.codec.binary.Base64InputStream;
|
import org.apache.commons.codec.binary.Base64InputStream;
|
||||||
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.fhir.ucum.Decimal;
|
||||||
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.PathEngineException;
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
|
@ -2125,17 +2127,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (type.equals("canonical")) {
|
if (type.equals("canonical")) {
|
||||||
ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, hostContext, path, url);
|
ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, hostContext, path, url);
|
||||||
if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) {
|
if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
||||||
} else {
|
} else {
|
||||||
hint(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
hint(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (url.contains("hl7.org") || url.contains("fhir.org")) {
|
if (url.contains("hl7.org") || url.contains("fhir.org")) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
||||||
} else if (url.contains("example.org") || url.contains("acme.com")) {
|
} else if (url.contains("example.org") || url.contains("acme.com")) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE, url);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE, url);
|
||||||
} else {
|
} else {
|
||||||
warning(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
warning(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2145,7 +2147,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
try {
|
try {
|
||||||
Resource r = fetcher.fetchCanonicalResource(this, url);
|
Resource r = fetcher.fetchCanonicalResource(this, url);
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
|
||||||
} else if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, isCorrectCanonicalType(r, context), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE, url, r.fhirType(), listExpectedCanonicalTypes(context))) {
|
} else if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, isCorrectCanonicalType(r, context), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE, url, r.fhirType(), listExpectedCanonicalTypes(context))) {
|
||||||
if (rp == ReferenceValidationPolicy.CHECK_VALID) {
|
if (rp == ReferenceValidationPolicy.CHECK_VALID) {
|
||||||
// todo....
|
// todo....
|
||||||
|
@ -2248,8 +2250,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (type.equals("decimal")) {
|
if (type.equals("decimal")) {
|
||||||
if (e.primitiveValue() != null) {
|
if (e.primitiveValue() != null) {
|
||||||
DecimalStatus ds = Utilities.checkDecimal(e.primitiveValue(), true, false);
|
DecimalStatus ds = Utilities.checkDecimal(e.primitiveValue(), true, false);
|
||||||
if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, ds == DecimalStatus.OK || ds == DecimalStatus.RANGE, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_VALID, e.primitiveValue()))
|
if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, ds == DecimalStatus.OK || ds == DecimalStatus.RANGE, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_VALID, e.primitiveValue())) {
|
||||||
warning(errors, IssueType.VALUE, e.line(), e.col(), path, ds != DecimalStatus.RANGE, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_RANGE, e.primitiveValue());
|
warning(errors, IssueType.VALUE, e.line(), e.col(), path, ds != DecimalStatus.RANGE, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_RANGE, e.primitiveValue());
|
||||||
|
try {
|
||||||
|
Decimal v = new Decimal(e.getValue());
|
||||||
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !context.hasMaxValueIntegerType() ||
|
||||||
|
!context.getMaxValueIntegerType().hasValue() || checkDecimalMaxValue(v, context.getMaxValueDecimalType().getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_GT, (context.hasMaxValueIntegerType() ? context.getMaxValueIntegerType() : ""));
|
||||||
|
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !context.hasMinValueIntegerType() ||
|
||||||
|
!context.getMinValueIntegerType().hasValue() || checkDecimalMinValue(v, context.getMaxValueDecimalType().getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_LT, (context.hasMinValueIntegerType() ? context.getMinValueIntegerType() : ""));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// should never happen?
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (context.hasExtension("http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces")) {
|
if (context.hasExtension("http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces")) {
|
||||||
int dp = e.primitiveValue().contains(".") ? e.primitiveValue().substring(e.primitiveValue().indexOf(".")+1).length() : 0;
|
int dp = e.primitiveValue().contains(".") ? e.primitiveValue().substring(e.primitiveValue().indexOf(".")+1).length() : 0;
|
||||||
|
@ -2615,7 +2627,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
checkFixedValue(errors, path + ".code", focus.getNamedChild("code"), fixed.getCodeElement(), fixedSource, "code", focus, pattern);
|
checkFixedValue(errors, path + ".code", focus.getNamedChild("code"), fixed.getCodeElement(), fixedSource, "code", focus, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkQuantity(List<ValidationMessage> theErrors, String thePath, Element element, StructureDefinition theProfile, ElementDefinition definition, NodeStack theStack) {
|
private void checkQuantity(List<ValidationMessage> errors, String path, Element element, StructureDefinition theProfile, ElementDefinition definition, NodeStack theStack) {
|
||||||
|
String value = element.hasChild("value") ? element.getNamedChild("value").getValue() : null;
|
||||||
String unit = element.hasChild("unit") ? element.getNamedChild("unit").getValue() : null;
|
String unit = element.hasChild("unit") ? element.getNamedChild("unit").getValue() : null;
|
||||||
String system = element.hasChild("system") ? element.getNamedChild("system").getValue() : null;
|
String system = element.hasChild("system") ? element.getNamedChild("system").getValue() : null;
|
||||||
String code = element.hasChild("code") ? element.getNamedChild("code").getValue() : null;
|
String code = element.hasChild("code") ? element.getNamedChild("code").getValue() : null;
|
||||||
|
@ -2623,24 +2636,122 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
// todo: allowedUnits http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits - codeableConcept, or canonical(ValueSet)
|
// todo: allowedUnits http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits - codeableConcept, or canonical(ValueSet)
|
||||||
// todo: http://hl7.org/fhir/StructureDefinition/iso21090-PQ-translation
|
// todo: http://hl7.org/fhir/StructureDefinition/iso21090-PQ-translation
|
||||||
|
|
||||||
if (definition.hasExtension("http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces")) {
|
if (!Utilities.noString(value) && definition.hasExtension("http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces")) {
|
||||||
String dec = element.getChildValue("value");
|
int dp = value.contains(".") ? value.substring(value.indexOf(".")+1).length() : 0;
|
||||||
int dp = dec.contains(".") ? dec.substring(dec.indexOf(".")+1).length() : 0;
|
|
||||||
int def = Integer.parseInt(ToolingExtensions.readStringExtension(definition, "http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces"));
|
int def = Integer.parseInt(ToolingExtensions.readStringExtension(definition, "http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces"));
|
||||||
rule(theErrors, IssueType.STRUCTURE, element.line(), element.col(), thePath, dp <= def, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS, dp, def);
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, dp <= def, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS, dp, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system != null || code != null ) {
|
if (system != null || code != null ) {
|
||||||
checkCodedElement(theErrors, thePath, element, theProfile, definition, false, false, theStack, code, system, null, unit);
|
checkCodedElement(errors, path, element, theProfile, definition, false, false, theStack, code, system, null, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code != null && "http://unitsofmeasure.org".equals(system)) {
|
if (code != null && "http://unitsofmeasure.org".equals(system)) {
|
||||||
int b = code.indexOf("{");
|
int b = code.indexOf("{");
|
||||||
int e = code.indexOf("}");
|
int e = code.indexOf("}");
|
||||||
if (b >= 0 && e > 0 && b < e) {
|
if (b >= 0 && e > 0 && b < e) {
|
||||||
bpCheck(theErrors, IssueType.BUSINESSRULE, element.line(), element.col(), thePath, !code.contains("{"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS, code.substring(b, e+1));
|
bpCheck(errors, IssueType.BUSINESSRULE, element.line(), element.col(), path, !code.contains("{"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS, code.substring(b, e+1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (definition.hasMinValue()) {
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(value), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_VALUE) &&
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, definition.getMinValue() instanceof Quantity, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_QTY, definition.getMinValue().fhirType())) {
|
||||||
|
Quantity min = definition.getMinValueQuantity();
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(min.getSystem()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_SYSTEM) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_SYSTEM) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, system.equals(min.getSystem()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_SYSTEM_MISMATCH, system, min.getSystem()) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(min.getCode()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CODE) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(code), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_NO_CODE) &&
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, definition.getMinValueQuantity().hasValue(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_VALUE)) {
|
||||||
|
if (code.equals(min.getCode())) {
|
||||||
|
// straight value comparison
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, checkDecimalMinValue(value, min.getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG, value, min.getValue().toString());
|
||||||
|
} else if ("http://unitsofmeasure.org".equals(system)) {
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, context.getUcumService() != null, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_NO_UCUM_SVC)) {
|
||||||
|
Decimal v = convertUcumValue(value, code, min.getCode());
|
||||||
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), path, v != null, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_MIN_NO_CONVERT, value, code, min.getCode())) {
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, checkDecimalMinValue(v, min.getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_VALUE_WRONG_UCUM, value, code, min.getValue().toString(), min.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MIN_CODE_MISMATCH, code, min.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.hasMaxValue()) {
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(value), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_VALUE) &&
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, definition.getMaxValue() instanceof Quantity, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_QTY, definition.getMaxValue().fhirType())) {
|
||||||
|
Quantity max = definition.getMaxValueQuantity();
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(max.getSystem()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_SYSTEM) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_SYSTEM) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, system.equals(max.getSystem()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_SYSTEM_MISMATCH, system, max.getSystem()) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(max.getCode()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CODE) &&
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, !Utilities.noString(code), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_NO_CODE) &&
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, definition.getMaxValueQuantity().hasValue(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_VALUE)) {
|
||||||
|
if (code.equals(max.getCode())) {
|
||||||
|
// straight value comparison
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, checkDecimalMaxValue(value, max.getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG, value, max.getValue().toString());
|
||||||
|
} else if ("http://unitsofmeasure.org".equals(system)) {
|
||||||
|
if (warning(errors, IssueType.INVALID, element.line(), element.col(), path, context.getUcumService() != null, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_NO_UCUM_SVC)) {
|
||||||
|
Decimal v = convertUcumValue(value, code, max.getCode());
|
||||||
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), path, v != null, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_MIN_NO_CONVERT, value, code, max.getCode())) {
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), path, checkDecimalMaxValue(v, max.getValue()), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM, value, code, max.getValue().toString(), max.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning(errors, IssueType.INVALID, element.line(), element.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_CODE_MISMATCH, code, max.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Decimal convertUcumValue(String value, String code, String minCode) {
|
||||||
|
try {
|
||||||
|
Decimal v = new Decimal(value);
|
||||||
|
return context.getUcumService().convert(v, code, minCode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkDecimalMaxValue(Decimal value, BigDecimal min) {
|
||||||
|
try {
|
||||||
|
Decimal m = new Decimal(min.toString());
|
||||||
|
return value.comparesTo(m) <= 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false; // this will be another error somewhere else?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkDecimalMaxValue(String value, BigDecimal min) {
|
||||||
|
try {
|
||||||
|
BigDecimal v = new BigDecimal(value);
|
||||||
|
return v.compareTo(min) <= 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false; // this will be another error somewhere else
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkDecimalMinValue(Decimal value, BigDecimal min) {
|
||||||
|
try {
|
||||||
|
Decimal m = new Decimal(min.toString());
|
||||||
|
return value.comparesTo(m) >= 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false; // this will be another error somewhere else?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkDecimalMinValue(String value, BigDecimal min) {
|
||||||
|
try {
|
||||||
|
BigDecimal v = new BigDecimal(value);
|
||||||
|
return v.compareTo(min) >= 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false; // this will be another error somewhere else
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAttachment(List<ValidationMessage> errors, String path, Element element, StructureDefinition theProfile, ElementDefinition definition, boolean theInCodeableConcept, boolean theCheckDisplayInContext, NodeStack theStack) {
|
private void checkAttachment(List<ValidationMessage> errors, String path, Element element, StructureDefinition theProfile, ElementDefinition definition, boolean theInCodeableConcept, boolean theCheckDisplayInContext, NodeStack theStack) {
|
||||||
|
@ -5408,8 +5519,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), resourceName.equals(defn.getType()), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE,
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), resourceName.equals(defn.getType()), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE,
|
||||||
defn.getType(), resourceName, defn.getUrl())) {
|
defn.getType(), resourceName, defn.getUrl())) {
|
||||||
start(hostContext, errors, element, element, defn, stack); // root is both definition and type
|
start(hostContext, errors, element, element, defn, stack); // root is both definition and type
|
||||||
} else {
|
|
||||||
System.out.println("what?");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue