Revert "Fixes for the translation of parameter issues as part of the output f…" (#6441)
This reverts commit fca3ea4445
.
This commit is contained in:
parent
fca3ea4445
commit
9365ad9509
|
@ -440,259 +440,74 @@ public interface IValidationSupport {
|
||||||
return "Unknown " + getFhirContext().getVersion().getVersion() + " Validation Support";
|
return "Unknown " + getFhirContext().getVersion().getVersion() + " Validation Support";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines codes in system <a href="http://hl7.org/fhir/issue-severity">http://hl7.org/fhir/issue-severity</a>.
|
|
||||||
*/
|
|
||||||
/* this enum would not be needed if we design/refactor to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult */
|
|
||||||
enum IssueSeverity {
|
enum IssueSeverity {
|
||||||
/**
|
/**
|
||||||
* The issue caused the action to fail, and no further checking could be performed.
|
* The issue caused the action to fail, and no further checking could be performed.
|
||||||
*/
|
*/
|
||||||
FATAL("fatal"),
|
FATAL,
|
||||||
/**
|
/**
|
||||||
* The issue is sufficiently important to cause the action to fail.
|
* The issue is sufficiently important to cause the action to fail.
|
||||||
*/
|
*/
|
||||||
ERROR("error"),
|
ERROR,
|
||||||
/**
|
/**
|
||||||
* The issue is not important enough to cause the action to fail, but may cause it to be performed suboptimally or in a way that is not as desired.
|
* The issue is not important enough to cause the action to fail, but may cause it to be performed suboptimally or in a way that is not as desired.
|
||||||
*/
|
*/
|
||||||
WARNING("warning"),
|
WARNING,
|
||||||
/**
|
/**
|
||||||
* The issue has no relation to the degree of success of the action.
|
* The issue has no relation to the degree of success of the action.
|
||||||
*/
|
*/
|
||||||
INFORMATION("information"),
|
INFORMATION
|
||||||
/**
|
|
||||||
* The operation was successful.
|
|
||||||
*/
|
|
||||||
SUCCESS("success");
|
|
||||||
// the spec for OperationOutcome mentions that a code from http://hl7.org/fhir/issue-severity is required
|
|
||||||
|
|
||||||
private final String myCode;
|
|
||||||
|
|
||||||
IssueSeverity(String theCode) {
|
|
||||||
myCode = theCode;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Provide mapping to a code in system <a href="http://hl7.org/fhir/issue-severity">http://hl7.org/fhir/issue-severity</a>.
|
|
||||||
* @return the code
|
|
||||||
*/
|
|
||||||
public String getCode() {
|
|
||||||
return myCode;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Creates a {@link IssueSeverity} object from the given code.
|
|
||||||
* @return the {@link IssueSeverity}
|
|
||||||
*/
|
|
||||||
public static IssueSeverity fromCode(String theCode) {
|
|
||||||
switch (theCode) {
|
|
||||||
case "fatal":
|
|
||||||
return FATAL;
|
|
||||||
case "error":
|
|
||||||
return ERROR;
|
|
||||||
case "warning":
|
|
||||||
return WARNING;
|
|
||||||
case "information":
|
|
||||||
return INFORMATION;
|
|
||||||
case "success":
|
|
||||||
return SUCCESS;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
enum CodeValidationIssueCode {
|
||||||
* Defines codes in system <a href="http://hl7.org/fhir/issue-type">http://hl7.org/fhir/issue-type</a>.
|
NOT_FOUND,
|
||||||
* The binding is enforced as a part of validation logic in the FHIR Core Validation library where an exception is thrown.
|
CODE_INVALID,
|
||||||
* Only a sub-set of these codes are defined as constants because they relate to validation,
|
INVALID,
|
||||||
* If there are additional ones that come up, for Remote Terminology they are currently supported via
|
OTHER
|
||||||
* {@link IValidationSupport.CodeValidationIssue#CodeValidationIssue(String, IssueSeverity, String)}
|
|
||||||
* while for internal validators, more constants can be added to make things easier and consistent.
|
|
||||||
* This maps to resource OperationOutcome.issue.code.
|
|
||||||
*/
|
|
||||||
/* this enum would not be needed if we design/refactor to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult */
|
|
||||||
class CodeValidationIssueCode {
|
|
||||||
public static final CodeValidationIssueCode NOT_FOUND = new CodeValidationIssueCode("not-found");
|
|
||||||
public static final CodeValidationIssueCode CODE_INVALID = new CodeValidationIssueCode("code-invalid");
|
|
||||||
public static final CodeValidationIssueCode INVALID = new CodeValidationIssueCode("invalid");
|
|
||||||
|
|
||||||
private final String myCode;
|
|
||||||
|
|
||||||
// this is intentionally not exposed
|
|
||||||
CodeValidationIssueCode(String theCode) {
|
|
||||||
myCode = theCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the corresponding code from system <a href="http://hl7.org/fhir/issue-type">http://hl7.org/fhir/issue-type</a>.
|
|
||||||
* @return the code
|
|
||||||
*/
|
|
||||||
public String getCode() {
|
|
||||||
return myCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
enum CodeValidationIssueCoding {
|
||||||
* Holds information about the details of a {@link CodeValidationIssue}.
|
VS_INVALID,
|
||||||
* This maps to resource OperationOutcome.issue.details.
|
NOT_FOUND,
|
||||||
*/
|
NOT_IN_VS,
|
||||||
/* this enum would not be needed if we design/refactor to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult */
|
|
||||||
class CodeValidationIssueDetails {
|
|
||||||
private final String myText;
|
|
||||||
private List<CodeValidationIssueCoding> myCodings;
|
|
||||||
|
|
||||||
public CodeValidationIssueDetails(String theText) {
|
INVALID_CODE,
|
||||||
myText = theText;
|
INVALID_DISPLAY,
|
||||||
}
|
OTHER
|
||||||
|
|
||||||
// intentionally not exposed
|
|
||||||
void addCoding(CodeValidationIssueCoding theCoding) {
|
|
||||||
getCodings().add(theCoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationIssueDetails addCoding(String theSystem, String theCode) {
|
|
||||||
if (myCodings == null) {
|
|
||||||
myCodings = new ArrayList<>();
|
|
||||||
}
|
|
||||||
myCodings.add(new CodeValidationIssueCoding(theSystem, theCode));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
return myText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<CodeValidationIssueCoding> getCodings() {
|
|
||||||
if (myCodings == null) {
|
|
||||||
myCodings = new ArrayList<>();
|
|
||||||
}
|
|
||||||
return myCodings;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines codes that can be part of the details of an issue.
|
|
||||||
* There are some constants available (pre-defined) for codes for system <a href="http://hl7.org/fhir/tools/CodeSystem/tx-issue-type">http://hl7.org/fhir/tools/CodeSystem/tx-issue-type</a>.
|
|
||||||
* This maps to resource OperationOutcome.issue.details.coding[0].code.
|
|
||||||
*/
|
|
||||||
class CodeValidationIssueCoding {
|
|
||||||
public static String TX_ISSUE_SYSTEM = "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type";
|
|
||||||
public static CodeValidationIssueCoding VS_INVALID =
|
|
||||||
new CodeValidationIssueCoding(TX_ISSUE_SYSTEM, "vs-invalid");
|
|
||||||
public static final CodeValidationIssueCoding NOT_FOUND =
|
|
||||||
new CodeValidationIssueCoding(TX_ISSUE_SYSTEM, "not-found");
|
|
||||||
public static final CodeValidationIssueCoding NOT_IN_VS =
|
|
||||||
new CodeValidationIssueCoding(TX_ISSUE_SYSTEM, "not-in-vs");
|
|
||||||
public static final CodeValidationIssueCoding INVALID_CODE =
|
|
||||||
new CodeValidationIssueCoding(TX_ISSUE_SYSTEM, "invalid-code");
|
|
||||||
public static final CodeValidationIssueCoding INVALID_DISPLAY =
|
|
||||||
new CodeValidationIssueCoding(TX_ISSUE_SYSTEM, "vs-display");
|
|
||||||
private final String mySystem, myCode;
|
|
||||||
|
|
||||||
// this is intentionally not exposed
|
|
||||||
CodeValidationIssueCoding(String theSystem, String theCode) {
|
|
||||||
mySystem = theSystem;
|
|
||||||
myCode = theCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the corresponding code for the details of a validation issue.
|
|
||||||
* @return the code
|
|
||||||
*/
|
|
||||||
public String getCode() {
|
|
||||||
return myCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the system for the details of a validation issue.
|
|
||||||
* @return the system
|
|
||||||
*/
|
|
||||||
public String getSystem() {
|
|
||||||
return mySystem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a hapi-fhir internal version agnostic object holding information about a validation issue.
|
|
||||||
* An alternative (which requires significant refactoring) would be to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult instead.
|
|
||||||
*/
|
|
||||||
class CodeValidationIssue {
|
class CodeValidationIssue {
|
||||||
private final String myDiagnostics;
|
|
||||||
|
private final String myMessage;
|
||||||
private final IssueSeverity mySeverity;
|
private final IssueSeverity mySeverity;
|
||||||
private final CodeValidationIssueCode myCode;
|
private final CodeValidationIssueCode myCode;
|
||||||
private CodeValidationIssueDetails myDetails;
|
private final CodeValidationIssueCoding myCoding;
|
||||||
|
|
||||||
public CodeValidationIssue(
|
public CodeValidationIssue(
|
||||||
String theDiagnostics, IssueSeverity theSeverity, CodeValidationIssueCode theTypeCode) {
|
String theMessage,
|
||||||
this(theDiagnostics, theSeverity, theTypeCode, null);
|
IssueSeverity mySeverity,
|
||||||
|
CodeValidationIssueCode theCode,
|
||||||
|
CodeValidationIssueCoding theCoding) {
|
||||||
|
this.myMessage = theMessage;
|
||||||
|
this.mySeverity = mySeverity;
|
||||||
|
this.myCode = theCode;
|
||||||
|
this.myCoding = theCoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeValidationIssue(String theDiagnostics, IssueSeverity theSeverity, String theTypeCode) {
|
|
||||||
this(theDiagnostics, theSeverity, new CodeValidationIssueCode(theTypeCode), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationIssue(
|
|
||||||
String theDiagnostics,
|
|
||||||
IssueSeverity theSeverity,
|
|
||||||
CodeValidationIssueCode theType,
|
|
||||||
CodeValidationIssueCoding theDetailsCoding) {
|
|
||||||
myDiagnostics = theDiagnostics;
|
|
||||||
mySeverity = theSeverity;
|
|
||||||
myCode = theType;
|
|
||||||
// reuse the diagnostics message as a detail text message
|
|
||||||
myDetails = new CodeValidationIssueDetails(theDiagnostics);
|
|
||||||
myDetails.addCoding(theDetailsCoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use {@link #getDiagnostics()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return getDiagnostics();
|
return myMessage;
|
||||||
}
|
|
||||||
|
|
||||||
public String getDiagnostics() {
|
|
||||||
return myDiagnostics;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IssueSeverity getSeverity() {
|
public IssueSeverity getSeverity() {
|
||||||
return mySeverity;
|
return mySeverity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use {@link #getType()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public CodeValidationIssueCode getCode() {
|
public CodeValidationIssueCode getCode() {
|
||||||
return getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationIssueCode getType() {
|
|
||||||
return myCode;
|
return myCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use {@link #getDetails()} instead. That has support for multiple codings.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public CodeValidationIssueCoding getCoding() {
|
public CodeValidationIssueCoding getCoding() {
|
||||||
return myDetails != null
|
return myCoding;
|
||||||
? myDetails.getCodings().stream().findFirst().orElse(null)
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDetails(CodeValidationIssueDetails theDetails) {
|
|
||||||
this.myDetails = theDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationIssueDetails getDetails() {
|
|
||||||
return myDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasIssueDetailCode(@Nonnull String theCode) {
|
|
||||||
// this method is system agnostic at the moment but it can be restricted if needed
|
|
||||||
return myDetails.getCodings().stream().anyMatch(coding -> theCode.equals(coding.getCode()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,10 +671,6 @@ public interface IValidationSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a hapi-fhir internal version agnostic object holding information about the validation result.
|
|
||||||
* An alternative (which requires significant refactoring) would be to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult.
|
|
||||||
*/
|
|
||||||
class CodeValidationResult {
|
class CodeValidationResult {
|
||||||
public static final String SOURCE_DETAILS = "sourceDetails";
|
public static final String SOURCE_DETAILS = "sourceDetails";
|
||||||
public static final String RESULT = "result";
|
public static final String RESULT = "result";
|
||||||
|
@ -875,7 +686,7 @@ public interface IValidationSupport {
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
private String mySourceDetails;
|
private String mySourceDetails;
|
||||||
|
|
||||||
private List<CodeValidationIssue> myIssues;
|
private List<CodeValidationIssue> myCodeValidationIssues;
|
||||||
|
|
||||||
public CodeValidationResult() {
|
public CodeValidationResult() {
|
||||||
super();
|
super();
|
||||||
|
@ -960,48 +771,23 @@ public interface IValidationSupport {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use method {@link #getIssues()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public List<CodeValidationIssue> getCodeValidationIssues() {
|
public List<CodeValidationIssue> getCodeValidationIssues() {
|
||||||
return getIssues();
|
if (myCodeValidationIssues == null) {
|
||||||
|
myCodeValidationIssues = new ArrayList<>();
|
||||||
|
}
|
||||||
|
return myCodeValidationIssues;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use method {@link #setIssues(List)} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public CodeValidationResult setCodeValidationIssues(List<CodeValidationIssue> theCodeValidationIssues) {
|
public CodeValidationResult setCodeValidationIssues(List<CodeValidationIssue> theCodeValidationIssues) {
|
||||||
return setIssues(theCodeValidationIssues);
|
myCodeValidationIssues = new ArrayList<>(theCodeValidationIssues);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Please use method {@link #addIssue(CodeValidationIssue)} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "7.4.6")
|
|
||||||
public CodeValidationResult addCodeValidationIssue(CodeValidationIssue theCodeValidationIssue) {
|
public CodeValidationResult addCodeValidationIssue(CodeValidationIssue theCodeValidationIssue) {
|
||||||
getCodeValidationIssues().add(theCodeValidationIssue);
|
getCodeValidationIssues().add(theCodeValidationIssue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CodeValidationIssue> getIssues() {
|
|
||||||
if (myIssues == null) {
|
|
||||||
myIssues = new ArrayList<>();
|
|
||||||
}
|
|
||||||
return myIssues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationResult setIssues(List<CodeValidationIssue> theIssues) {
|
|
||||||
myIssues = new ArrayList<>(theIssues);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeValidationResult addIssue(CodeValidationIssue theCodeValidationIssue) {
|
|
||||||
getIssues().add(theCodeValidationIssue);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
public boolean isOk() {
|
||||||
return isNotBlank(myCode);
|
return isNotBlank(myCode);
|
||||||
}
|
}
|
||||||
|
@ -1025,19 +811,17 @@ public interface IValidationSupport {
|
||||||
public String getSeverityCode() {
|
public String getSeverityCode() {
|
||||||
String retVal = null;
|
String retVal = null;
|
||||||
if (getSeverity() != null) {
|
if (getSeverity() != null) {
|
||||||
retVal = getSeverity().getCode();
|
retVal = getSeverity().name().toLowerCase();
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an issue severity using a severity code. Please use method {@link #setSeverity(IssueSeverity)} instead.
|
* Sets an issue severity as a string code. Value must be the name of
|
||||||
* @param theSeverityCode the code
|
* one of the enum values in {@link IssueSeverity}. Value is case-insensitive.
|
||||||
* @return the current {@link CodeValidationResult} instance
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "7.4.6")
|
public CodeValidationResult setSeverityCode(@Nonnull String theIssueSeverity) {
|
||||||
public CodeValidationResult setSeverityCode(@Nonnull String theSeverityCode) {
|
setSeverity(IssueSeverity.valueOf(theIssueSeverity.toUpperCase()));
|
||||||
setSeverity(IssueSeverity.fromCode(theSeverityCode));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,11 +838,6 @@ public interface IValidationSupport {
|
||||||
if (isNotBlank(getSourceDetails())) {
|
if (isNotBlank(getSourceDetails())) {
|
||||||
ParametersUtil.addParameterToParametersString(theContext, retVal, SOURCE_DETAILS, getSourceDetails());
|
ParametersUtil.addParameterToParametersString(theContext, retVal, SOURCE_DETAILS, getSourceDetails());
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
should translate issues as well, except that is version specific code, so it requires more refactoring
|
|
||||||
or replace the current class with org.hl7.fhir.r5.terminologies.utilities.ValidationResult
|
|
||||||
@see VersionSpecificWorkerContextWrapper#getIssuesForCodeValidation
|
|
||||||
*/
|
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
type: fix
|
|
||||||
issue: 6422
|
|
||||||
title: "Previously, since 7.4.4 the validation issue detail codes were not translated correctly for Remote Terminology
|
|
||||||
validateCode calls. The detail code used was `invalid-code` for all use-cases which resulted in profile binding strength
|
|
||||||
not being applied to the issue severity as expected when validating resources against a profile.
|
|
||||||
This has been fixed and issue detail codes are translated correctly."
|
|
|
@ -1044,8 +1044,7 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
||||||
if (theExpansionOptions != null
|
if (theExpansionOptions != null
|
||||||
&& !theExpansionOptions.isFailOnMissingCodeSystem()
|
&& !theExpansionOptions.isFailOnMissingCodeSystem()
|
||||||
// Code system is unknown, therefore NOT_FOUND
|
// Code system is unknown, therefore NOT_FOUND
|
||||||
&& e.getCodeValidationIssue()
|
&& e.getCodeValidationIssue().getCoding() == CodeValidationIssueCoding.NOT_FOUND) {
|
||||||
.hasIssueDetailCode(CodeValidationIssueCoding.NOT_FOUND.getCode())) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new InternalErrorException(Msg.code(888) + e);
|
throw new InternalErrorException(Msg.code(888) + e);
|
||||||
|
@ -2191,7 +2190,7 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
||||||
.setSeverity(IssueSeverity.ERROR)
|
.setSeverity(IssueSeverity.ERROR)
|
||||||
.setCodeSystemVersion(theCodeSystemVersion)
|
.setCodeSystemVersion(theCodeSystemVersion)
|
||||||
.setMessage(theMessage)
|
.setMessage(theMessage)
|
||||||
.addIssue(new CodeValidationIssue(
|
.addCodeValidationIssue(new CodeValidationIssue(
|
||||||
theMessage,
|
theMessage,
|
||||||
IssueSeverity.ERROR,
|
IssueSeverity.ERROR,
|
||||||
CodeValidationIssueCode.CODE_INVALID,
|
CodeValidationIssueCode.CODE_INVALID,
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.validation;
|
package ca.uhn.fhir.jpa.provider.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.config.JpaConfig;
|
import ca.uhn.fhir.jpa.config.JpaConfig;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.param.UriParam;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersR4;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.BooleanType;
|
import org.hl7.fhir.r4.model.BooleanType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
import org.hl7.fhir.r4.model.CodeType;
|
import org.hl7.fhir.r4.model.CodeType;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
import org.hl7.fhir.r4.model.UriType;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -25,7 +33,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_VALIDATE_CODE;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
@ -33,15 +43,15 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This set of integration tests that instantiates and injects an instance of
|
* This set of integration tests that instantiates and injects an instance of
|
||||||
* {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport}
|
* {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport}
|
||||||
* into the ValidationSupportChain, which tests the logic of dynamically selecting the correct Remote Terminology
|
* into the ValidationSupportChain, which tests the logic of dynamically selecting the correct Remote Terminology
|
||||||
* implementation. It also exercises the validateCode output translation code found in
|
* implementation. It also exercises the code found in
|
||||||
* {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport}
|
* {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport#invokeRemoteValidateCode}
|
||||||
*/
|
*/
|
||||||
public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProviderR4Test {
|
public class ValidateCodeOperationWithRemoteTerminologyR4Test extends BaseResourceProviderR4Test {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateCodeWithRemoteTerminologyR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateCodeOperationWithRemoteTerminologyR4Test.class);
|
||||||
private static final String DISPLAY = "DISPLAY";
|
private static final String DISPLAY = "DISPLAY";
|
||||||
private static final String DISPLAY_BODY_MASS_INDEX = "Body mass index (BMI) [Ratio]";
|
private static final String DISPLAY_BODY_MASS_INDEX = "Body mass index (BMI) [Ratio]";
|
||||||
private static final String CODE_BODY_MASS_INDEX = "39156-5";
|
private static final String CODE_BODY_MASS_INDEX = "39156-5";
|
||||||
|
@ -54,8 +64,8 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
protected static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
protected static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
|
|
||||||
private RemoteTerminologyServiceValidationSupport mySvc;
|
private RemoteTerminologyServiceValidationSupport mySvc;
|
||||||
private IValidationProviders.MyValidationProvider<CodeSystem> myCodeSystemProvider;
|
private MyCodeSystemProvider myCodeSystemProvider;
|
||||||
private IValidationProviders.MyValidationProvider<ValueSet> myValueSetProvider;
|
private MyValueSetProvider myValueSetProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN)
|
@Qualifier(JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN)
|
||||||
|
@ -66,8 +76,8 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
||||||
myValidationSupportChain.addValidationSupport(0, mySvc);
|
myValidationSupportChain.addValidationSupport(0, mySvc);
|
||||||
myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4();
|
myCodeSystemProvider = new MyCodeSystemProvider();
|
||||||
myValueSetProvider = new IValidationProvidersR4.MyValueSetProviderR4();
|
myValueSetProvider = new MyValueSetProvider();
|
||||||
ourRestfulServerExtension.registerProvider(myCodeSystemProvider);
|
ourRestfulServerExtension.registerProvider(myCodeSystemProvider);
|
||||||
ourRestfulServerExtension.registerProvider(myValueSetProvider);
|
ourRestfulServerExtension.registerProvider(myValueSetProvider);
|
||||||
}
|
}
|
||||||
|
@ -93,11 +103,11 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCodeOperationOnCodeSystem_byCodingAndUrl_usingBuiltInCodeSystems() {
|
public void validateCodeOperationOnCodeSystem_byCodingAndUrl_usingBuiltInCodeSystems() {
|
||||||
final String code = "P";
|
myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>();
|
||||||
final String system = CODE_SYSTEM_V2_0247_URI;;
|
myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/v2-0247"));
|
||||||
|
myCodeSystemProvider.myReturnParams = new Parameters();
|
||||||
Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY);
|
myCodeSystemProvider.myReturnParams.addParameter("result", true);
|
||||||
setupCodeSystemValidateCode(system, code, params);
|
myCodeSystemProvider.myReturnParams.addParameter("display", DISPLAY);
|
||||||
|
|
||||||
logAllConcepts();
|
logAllConcepts();
|
||||||
|
|
||||||
|
@ -105,8 +115,8 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
.operation()
|
.operation()
|
||||||
.onType(CodeSystem.class)
|
.onType(CodeSystem.class)
|
||||||
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
||||||
.withParameter(Parameters.class, "coding", new Coding().setSystem(system).setCode(code))
|
.withParameter(Parameters.class, "coding", new Coding().setSystem(CODE_SYSTEM_V2_0247_URI).setCode("P"))
|
||||||
.andParameter("url", new UriType(system))
|
.andParameter("url", new UriType(CODE_SYSTEM_V2_0247_URI))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||||
|
@ -118,7 +128,7 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCodeOperationOnCodeSystem_byCodingAndUrlWhereCodeSystemIsUnknown_returnsFalse() {
|
public void validateCodeOperationOnCodeSystem_byCodingAndUrlWhereCodeSystemIsUnknown_returnsFalse() {
|
||||||
myCodeSystemProvider.setShouldThrowExceptionForResourceNotFound(false);
|
myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>();
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
|
@ -156,21 +166,21 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCodeOperationOnValueSet_byUrlAndSystem_usingBuiltInCodeSystems() {
|
public void validateCodeOperationOnValueSet_byUrlAndSystem_usingBuiltInCodeSystems() {
|
||||||
final String code = "alerts";
|
myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>();
|
||||||
final String system = "http://terminology.hl7.org/CodeSystem/list-example-use-codes";
|
myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/list-example-use-codes"));
|
||||||
final String valueSetUrl = "http://hl7.org/fhir/ValueSet/list-example-codes";
|
myValueSetProvider.myReturnValueSets = new ArrayList<>();
|
||||||
|
myValueSetProvider.myReturnValueSets.add((ValueSet) new ValueSet().setId("ValueSet/list-example-codes"));
|
||||||
Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY);
|
myValueSetProvider.myReturnParams = new Parameters();
|
||||||
setupValueSetValidateCode(valueSetUrl, system, code, params);
|
myValueSetProvider.myReturnParams.addParameter("result", true);
|
||||||
setupCodeSystemValidateCode(system, code, params);
|
myValueSetProvider.myReturnParams.addParameter("display", DISPLAY);
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
.onType(ValueSet.class)
|
.onType(ValueSet.class)
|
||||||
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
||||||
.withParameter(Parameters.class, "code", new CodeType(code))
|
.withParameter(Parameters.class, "code", new CodeType("alerts"))
|
||||||
.andParameter("system", new UriType(system))
|
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/list-example-use-codes"))
|
||||||
.andParameter("url", new UriType(valueSetUrl))
|
.andParameter("url", new UriType("http://hl7.org/fhir/ValueSet/list-example-codes"))
|
||||||
.useHttpGet()
|
.useHttpGet()
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
@ -183,20 +193,21 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCodeOperationOnValueSet_byUrlSystemAndCode() {
|
public void validateCodeOperationOnValueSet_byUrlSystemAndCode() {
|
||||||
final String code = CODE_BODY_MASS_INDEX;
|
myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>();
|
||||||
final String system = "http://terminology.hl7.org/CodeSystem/list-example-use-codes";
|
myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/list-example-use-codes"));
|
||||||
final String valueSetUrl = "http://hl7.org/fhir/ValueSet/list-example-codes";
|
myValueSetProvider.myReturnValueSets = new ArrayList<>();
|
||||||
|
myValueSetProvider.myReturnValueSets.add((ValueSet) new ValueSet().setId("ValueSet/list-example-codes"));
|
||||||
Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY_BODY_MASS_INDEX);
|
myValueSetProvider.myReturnParams = new Parameters();
|
||||||
setupValueSetValidateCode(valueSetUrl, system, code, params);
|
myValueSetProvider.myReturnParams.addParameter("result", true);
|
||||||
|
myValueSetProvider.myReturnParams.addParameter("display", DISPLAY_BODY_MASS_INDEX);
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
.onType(ValueSet.class)
|
.onType(ValueSet.class)
|
||||||
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
.named(JpaConstants.OPERATION_VALIDATE_CODE)
|
||||||
.withParameter(Parameters.class, "code", new CodeType(code))
|
.withParameter(Parameters.class, "code", new CodeType(CODE_BODY_MASS_INDEX))
|
||||||
.andParameter("url", new UriType(valueSetUrl))
|
.andParameter("url", new UriType("https://loinc.org"))
|
||||||
.andParameter("system", new UriType(system))
|
.andParameter("system", new UriType("http://loinc.org"))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||||
|
@ -208,7 +219,7 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCodeOperationOnValueSet_byCodingAndUrlWhereValueSetIsUnknown_returnsFalse() {
|
public void validateCodeOperationOnValueSet_byCodingAndUrlWhereValueSetIsUnknown_returnsFalse() {
|
||||||
myValueSetProvider.setShouldThrowExceptionForResourceNotFound(false);
|
myValueSetProvider.myReturnValueSets = new ArrayList<>();
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
|
@ -227,18 +238,70 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide
|
||||||
" - Unknown or unusable ValueSet[" + UNKNOWN_VALUE_SYSTEM_URI + "]");
|
" - Unknown or unusable ValueSet[" + UNKNOWN_VALUE_SYSTEM_URI + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupValueSetValidateCode(String theUrl, String theSystem, String theCode, IBaseParameters theResponseParams) {
|
@SuppressWarnings("unused")
|
||||||
ValueSet valueSet = myValueSetProvider.addTerminologyResource(theUrl);
|
private static class MyCodeSystemProvider implements IResourceProvider {
|
||||||
myValueSetProvider.addTerminologyResource(theSystem);
|
private List<CodeSystem> myReturnCodeSystems;
|
||||||
myValueSetProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, valueSet.getUrl(), theCode, theResponseParams);
|
private Parameters myReturnParams;
|
||||||
|
|
||||||
// we currently do this because VersionSpecificWorkerContextWrapper has logic to infer the system when missing
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
// based on the ValueSet by calling ValidationSupportUtils#extractCodeSystemForCode.
|
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
||||||
valueSet.getCompose().addInclude().setSystem(theSystem);
|
@OperationParam(name = "message", type = StringType.class),
|
||||||
|
@OperationParam(name = "display", type = StringType.class)
|
||||||
|
})
|
||||||
|
public Parameters validateCode(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
@IdParam(optional = true) IdType theId,
|
||||||
|
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
|
||||||
|
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
||||||
|
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay
|
||||||
|
) {
|
||||||
|
return myReturnParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public List<CodeSystem> find(@RequiredParam(name = "url") UriParam theUrlParam) {
|
||||||
|
assert myReturnCodeSystems != null;
|
||||||
|
return myReturnCodeSystems;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return CodeSystem.class;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupCodeSystemValidateCode(String theUrl, String theCode, IBaseParameters theResponseParams) {
|
@SuppressWarnings("unused")
|
||||||
CodeSystem codeSystem = myCodeSystemProvider.addTerminologyResource(theUrl);
|
private static class MyValueSetProvider implements IResourceProvider {
|
||||||
myCodeSystemProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, codeSystem.getUrl(), theCode, theResponseParams);
|
private Parameters myReturnParams;
|
||||||
|
private List<ValueSet> myReturnValueSets;
|
||||||
|
|
||||||
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
|
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
||||||
|
@OperationParam(name = "message", type = StringType.class),
|
||||||
|
@OperationParam(name = "display", type = StringType.class)
|
||||||
|
})
|
||||||
|
public Parameters validateCode(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
@IdParam(optional = true) IdType theId,
|
||||||
|
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
|
||||||
|
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
||||||
|
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
|
||||||
|
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
|
||||||
|
@OperationParam(name = "valueSet") ValueSet theValueSet
|
||||||
|
) {
|
||||||
|
return myReturnParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public List<ValueSet> find(@RequiredParam(name = "url") UriParam theUrlParam) {
|
||||||
|
assert myReturnValueSets != null;
|
||||||
|
return myReturnValueSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return ValueSet.class;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,261 +0,0 @@
|
||||||
package ca.uhn.fhir.jpa.validation;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.jpa.config.JpaConfig;
|
|
||||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersR4;
|
|
||||||
import ca.uhn.fhir.util.ClasspathUtil;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
|
||||||
import org.hl7.fhir.r4.model.Encounter;
|
|
||||||
import org.hl7.fhir.r4.model.Observation;
|
|
||||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
|
||||||
import org.hl7.fhir.r4.model.Procedure;
|
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
|
||||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_VALIDATE_CODE;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests resource validation with Remote Terminology bindings.
|
|
||||||
* To create a new test, you need to do 3 things:
|
|
||||||
* (1) the resource profile, if any custom one is needed should be stored in the FHIR repository
|
|
||||||
* (2) all the CodeSystem and ValueSet terminology resources need to be added to the corresponding resource provider.
|
|
||||||
* At the moment only placeholder CodeSystem/ValueSet resources are returned with id and url populated. For the moment
|
|
||||||
* there was no need to load the full resource, but that can be done if there is logic run which requires it.
|
|
||||||
* This is a minimal setup.
|
|
||||||
* (3) the Remote Terminology operation responses that are needed for the test need to be added to the corresponding
|
|
||||||
* resource provider. The intention is to record and use the responses of an actual terminology server
|
|
||||||
* e.g. <a href="https://r4.ontoserver.csiro.au/fhir/">OntoServer</a>.
|
|
||||||
* This is done as a result of the fact that unit test cannot always catch bugs which are introduced as a result of
|
|
||||||
* changes in the OntoServer or FHIR Validator library, or both.
|
|
||||||
* @see #setupValueSetValidateCode
|
|
||||||
* @see #setupCodeSystemValidateCode
|
|
||||||
* The responses are in Parameters resource format where issues is an OperationOutcome resource.
|
|
||||||
*/
|
|
||||||
public class ValidateWithRemoteTerminologyTest extends BaseResourceProviderR4Test {
|
|
||||||
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
protected static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
|
||||||
private RemoteTerminologyServiceValidationSupport mySvc;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier(JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN)
|
|
||||||
private ValidationSupportChain myValidationSupportChain;
|
|
||||||
private IValidationProviders.MyValidationProvider<CodeSystem> myCodeSystemProvider;
|
|
||||||
private IValidationProviders.MyValidationProvider<ValueSet> myValueSetProvider;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void before() {
|
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
|
||||||
myValidationSupportChain.addValidationSupport(0, mySvc);
|
|
||||||
myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4();
|
|
||||||
myValueSetProvider = new IValidationProvidersR4.MyValueSetProviderR4();
|
|
||||||
ourRestfulServerExtension.registerProvider(myCodeSystemProvider);
|
|
||||||
ourRestfulServerExtension.registerProvider(myValueSetProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
public void after() {
|
|
||||||
myValidationSupportChain.removeValidationSupport(mySvc);
|
|
||||||
ourRestfulServerExtension.getRestfulServer().getInterceptorService().unregisterAllInterceptors();
|
|
||||||
ourRestfulServerExtension.unregisterProvider(myCodeSystemProvider);
|
|
||||||
ourRestfulServerExtension.unregisterProvider(myValueSetProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validate_withProfileWithValidCodesFromAllBindingTypes_returnsNoErrors() {
|
|
||||||
// setup
|
|
||||||
final StructureDefinition profileEncounter = ClasspathUtil.loadResource(ourCtx, StructureDefinition.class, "validation/encounter/profile-encounter-custom.json");
|
|
||||||
myClient.update().resource(profileEncounter).execute();
|
|
||||||
|
|
||||||
final String statusCode = "planned";
|
|
||||||
final String classCode = "IMP";
|
|
||||||
final String identifierTypeCode = "VN";
|
|
||||||
|
|
||||||
final String statusSystem = "http://hl7.org/fhir/encounter-status"; // implied system
|
|
||||||
final String classSystem = "http://terminology.hl7.org/CodeSystem/v3-ActCode";
|
|
||||||
final String identifierTypeSystem = "http://terminology.hl7.org/CodeSystem/v2-0203";
|
|
||||||
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/encounter-status", "http://hl7.org/fhir/encounter-status", statusCode, "validation/encounter/validateCode-ValueSet-encounter-status.json");
|
|
||||||
setupValueSetValidateCode("http://terminology.hl7.org/ValueSet/v3-ActEncounterCode", "http://terminology.hl7.org/CodeSystem/v3-ActCode", classCode, "validation/encounter/validateCode-ValueSet-v3-ActEncounterCode.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/identifier-type", "http://hl7.org/fhir/identifier-type", identifierTypeCode, "validation/encounter/validateCode-ValueSet-identifier-type.json");
|
|
||||||
|
|
||||||
setupCodeSystemValidateCode(statusSystem, statusCode, "validation/encounter/validateCode-CodeSystem-encounter-status.json");
|
|
||||||
setupCodeSystemValidateCode(classSystem, classCode, "validation/encounter/validateCode-CodeSystem-v3-ActCode.json");
|
|
||||||
setupCodeSystemValidateCode(identifierTypeSystem, identifierTypeCode, "validation/encounter/validateCode-CodeSystem-v2-0203.json");
|
|
||||||
|
|
||||||
Encounter encounter = new Encounter();
|
|
||||||
encounter.getMeta().addProfile("http://example.ca/fhir/StructureDefinition/profile-encounter");
|
|
||||||
|
|
||||||
// required binding
|
|
||||||
encounter.setStatus(Encounter.EncounterStatus.fromCode(statusCode));
|
|
||||||
|
|
||||||
// preferred binding
|
|
||||||
encounter.getClass_()
|
|
||||||
.setSystem(classSystem)
|
|
||||||
.setCode(classCode)
|
|
||||||
.setDisplay("inpatient encounter");
|
|
||||||
|
|
||||||
// extensible binding
|
|
||||||
encounter.addIdentifier()
|
|
||||||
.getType().addCoding()
|
|
||||||
.setSystem(identifierTypeSystem)
|
|
||||||
.setCode(identifierTypeCode)
|
|
||||||
.setDisplay("Visit number");
|
|
||||||
|
|
||||||
// execute
|
|
||||||
List<String> errors = getValidationErrors(encounter);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
assertThat(errors).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validate_withInvalidCode_returnsErrors() {
|
|
||||||
// setup
|
|
||||||
final String statusCode = "final";
|
|
||||||
final String code = "10xx";
|
|
||||||
|
|
||||||
final String statusSystem = "http://hl7.org/fhir/observation-status";
|
|
||||||
final String loincSystem = "http://loinc.org";
|
|
||||||
final String system = "http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM";
|
|
||||||
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/observation-status", statusSystem, statusCode, "validation/observation/validateCode-ValueSet-observation-status.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/observation-codes", loincSystem, statusCode, "validation/observation/validateCode-ValueSet-codes.json");
|
|
||||||
|
|
||||||
setupCodeSystemValidateCode(statusSystem, statusCode, "validation/observation/validateCode-CodeSystem-observation-status.json");
|
|
||||||
setupCodeSystemValidateCode(system, code, "validation/observation/validateCode-CodeSystem-ICD9CM.json");
|
|
||||||
|
|
||||||
Observation obs = new Observation();
|
|
||||||
obs.setStatus(Observation.ObservationStatus.fromCode(statusCode));
|
|
||||||
obs.getCode().addCoding().setCode(code).setSystem(system);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
List<String> errors = getValidationErrors(obs);
|
|
||||||
assertThat(errors).hasSize(1);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
assertThat(errors.get(0))
|
|
||||||
.contains("Unknown code '10xx' in the CodeSystem 'http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validate_withProfileWithInvalidCode_returnsErrors() {
|
|
||||||
// setup
|
|
||||||
String profile = "http://example.ca/fhir/StructureDefinition/profile-procedure";
|
|
||||||
StructureDefinition profileProcedure = ClasspathUtil.loadResource(myFhirContext, StructureDefinition.class, "validation/procedure/profile-procedure.json");
|
|
||||||
myClient.update().resource(profileProcedure).execute();
|
|
||||||
|
|
||||||
final String statusCode = "completed";
|
|
||||||
final String procedureCode1 = "417005";
|
|
||||||
final String procedureCode2 = "xx417005";
|
|
||||||
|
|
||||||
final String statusSystem = "http://hl7.org/fhir/event-status";
|
|
||||||
final String snomedSystem = "http://snomed.info/sct";
|
|
||||||
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/event-status", statusSystem, statusCode, "validation/procedure/validateCode-ValueSet-event-status.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/procedure-code", snomedSystem, procedureCode1, "validation/procedure/validateCode-ValueSet-procedure-code-valid.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/procedure-code", snomedSystem, procedureCode2, "validation/procedure/validateCode-ValueSet-procedure-code-invalid.json");
|
|
||||||
|
|
||||||
setupCodeSystemValidateCode(statusSystem, statusCode, "validation/procedure/validateCode-CodeSystem-event-status.json");
|
|
||||||
setupCodeSystemValidateCode(snomedSystem, procedureCode1, "validation/procedure/validateCode-CodeSystem-snomed-valid.json");
|
|
||||||
setupCodeSystemValidateCode(snomedSystem, procedureCode2, "validation/procedure/validateCode-CodeSystem-snomed-invalid.json");
|
|
||||||
|
|
||||||
Procedure procedure = new Procedure();
|
|
||||||
procedure.setSubject(new Reference("Patient/P1"));
|
|
||||||
procedure.setStatus(Procedure.ProcedureStatus.fromCode(statusCode));
|
|
||||||
procedure.getCode().addCoding().setSystem(snomedSystem).setCode(procedureCode1);
|
|
||||||
procedure.getCode().addCoding().setSystem(snomedSystem).setCode(procedureCode2);
|
|
||||||
procedure.getMeta().addProfile(profile);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
List<String> errors = getValidationErrors(procedure);
|
|
||||||
// TODO: there is currently some duplication in the errors returned. This needs to be investigated and fixed.
|
|
||||||
// assertThat(errors).hasSize(1);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
// note that we're not selecting an explicit versions (using latest) so the message verification does not include it.
|
|
||||||
assertThat(StringUtils.join("", errors))
|
|
||||||
.contains("Unknown code 'xx417005' in the CodeSystem 'http://snomed.info/sct'")
|
|
||||||
.doesNotContain("The provided code 'http://snomed.info/sct#xx417005' was not found in the value set 'http://hl7.org/fhir/ValueSet/procedure-code")
|
|
||||||
.doesNotContain("http://snomed.info/sct#417005");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validate_withProfileWithSlicingWithValidCode_returnsNoErrors() {
|
|
||||||
// setup
|
|
||||||
String profile = "http://example.ca/fhir/StructureDefinition/profile-procedure-with-slicing";
|
|
||||||
StructureDefinition profileProcedure = ClasspathUtil.loadResource(myFhirContext, StructureDefinition.class, "validation/procedure/profile-procedure-slicing.json");
|
|
||||||
myClient.update().resource(profileProcedure).execute();
|
|
||||||
|
|
||||||
final String statusCode = "completed";
|
|
||||||
final String procedureCode = "no-procedure-info";
|
|
||||||
|
|
||||||
final String statusSystem = "http://hl7.org/fhir/event-status";
|
|
||||||
final String snomedSystem = "http://snomed.info/sct";
|
|
||||||
final String absentUnknownSystem = "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips";
|
|
||||||
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/event-status", statusSystem, statusCode, "validation/procedure/validateCode-ValueSet-event-status.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/ValueSet/procedure-code", snomedSystem, procedureCode, "validation/procedure/validateCode-ValueSet-procedure-code-invalid-slice.json");
|
|
||||||
setupValueSetValidateCode("http://hl7.org/fhir/uv/ips/ValueSet/absent-or-unknown-procedures-uv-ips", absentUnknownSystem, procedureCode, "validation/procedure/validateCode-ValueSet-absent-or-unknown-procedure.json");
|
|
||||||
|
|
||||||
setupCodeSystemValidateCode(statusSystem, statusCode, "validation/procedure/validateCode-CodeSystem-event-status.json");
|
|
||||||
setupCodeSystemValidateCode(absentUnknownSystem, procedureCode, "validation/procedure/validateCode-CodeSystem-absent-or-unknown.json");
|
|
||||||
|
|
||||||
Procedure procedure = new Procedure();
|
|
||||||
procedure.setSubject(new Reference("Patient/P1"));
|
|
||||||
procedure.setStatus(Procedure.ProcedureStatus.fromCode(statusCode));
|
|
||||||
procedure.getCode().addCoding().setSystem(absentUnknownSystem).setCode(procedureCode);
|
|
||||||
procedure.getMeta().addProfile(profile);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
List<String> errors = getValidationErrors(procedure);
|
|
||||||
assertThat(errors).hasSize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupValueSetValidateCode(String theUrl, String theSystem, String theCode, String theTerminologyResponseFile) {
|
|
||||||
ValueSet valueSet = myValueSetProvider.addTerminologyResource(theUrl);
|
|
||||||
myCodeSystemProvider.addTerminologyResource(theSystem);
|
|
||||||
myValueSetProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, valueSet.getUrl(), theCode, ourCtx, theTerminologyResponseFile);
|
|
||||||
|
|
||||||
// we currently do this because VersionSpecificWorkerContextWrapper has logic to infer the system when missing
|
|
||||||
// based on the ValueSet by calling ValidationSupportUtils#extractCodeSystemForCode.
|
|
||||||
valueSet.getCompose().addInclude().setSystem(theSystem);
|
|
||||||
|
|
||||||
// you will notice each of these calls require also a call to setupCodeSystemValidateCode
|
|
||||||
// that is necessary because VersionSpecificWorkerContextWrapper#validateCodeInValueSet
|
|
||||||
// which also attempts a validateCode against the CodeSystem after the validateCode against the ValueSet
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCodeSystemValidateCode(String theUrl, String theCode, String theTerminologyResponseFile) {
|
|
||||||
CodeSystem codeSystem = myCodeSystemProvider.addTerminologyResource(theUrl);
|
|
||||||
myCodeSystemProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, codeSystem.getUrl(), theCode, ourCtx, theTerminologyResponseFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getValidationErrors(IBaseResource theResource) {
|
|
||||||
MethodOutcome resultProcedure = myClient.validate().resource(theResource).execute();
|
|
||||||
OperationOutcome operationOutcome = (OperationOutcome) resultProcedure.getOperationOutcome();
|
|
||||||
return operationOutcome.getIssue().stream()
|
|
||||||
.filter(issue -> issue.getSeverity() == OperationOutcome.IssueSeverity.ERROR)
|
|
||||||
.map(OperationOutcome.OperationOutcomeIssueComponent::getDiagnostics)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "StructureDefinition",
|
|
||||||
"id": "profile-encounter",
|
|
||||||
"url": "http://example.ca/fhir/StructureDefinition/profile-encounter",
|
|
||||||
"version": "0.11.0",
|
|
||||||
"name": "EncounterProfile",
|
|
||||||
"title": "Encounter Profile",
|
|
||||||
"status": "active",
|
|
||||||
"date": "2022-10-15T12:00:00+00:00",
|
|
||||||
"publisher": "Example Organization",
|
|
||||||
"fhirVersion": "4.0.1",
|
|
||||||
"kind": "resource",
|
|
||||||
"abstract": false,
|
|
||||||
"type": "Encounter",
|
|
||||||
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Encounter",
|
|
||||||
"derivation": "constraint",
|
|
||||||
"differential": {
|
|
||||||
"element": [
|
|
||||||
{
|
|
||||||
"id": "Encounter.identifier.type.coding",
|
|
||||||
"path": "Encounter.identifier.type.coding",
|
|
||||||
"min": 1,
|
|
||||||
"max": "1",
|
|
||||||
"mustSupport": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Encounter.identifier.type.coding.system",
|
|
||||||
"path": "Encounter.identifier.type.coding.system",
|
|
||||||
"min": 1,
|
|
||||||
"fixedUri": "http://terminology.hl7.org/CodeSystem/v2-0203",
|
|
||||||
"mustSupport": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Encounter.identifier.type.coding.code",
|
|
||||||
"path": "Encounter.identifier.type.coding.code",
|
|
||||||
"min": 1,
|
|
||||||
"fixedCode": "VN",
|
|
||||||
"mustSupport": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Encounter.identifier.type.coding.display",
|
|
||||||
"path": "Encounter.identifier.type.coding.display",
|
|
||||||
"min": 1,
|
|
||||||
"fixedString": "Visit number",
|
|
||||||
"mustSupport": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "planned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/encounter-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Planned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use CodeSystem http://hl7.org/fhir/encounter-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to draft CodeSystem http://hl7.org/fhir/encounter-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "VN"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://terminology.hl7.org/CodeSystem/v2-0203"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "3.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Visit number"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "IMP"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "2018-08-12"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "inpatient encounter"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to draft CodeSystem http://terminology.hl7.org/CodeSystem/v3-ActCode|2018-08-12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "planned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/encounter-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Planned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use CodeSystem http://hl7.org/fhir/encounter-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to draft CodeSystem http://hl7.org/fhir/encounter-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "VN"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://terminology.hl7.org/CodeSystem/v2-0203"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "3.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "not-in-vs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "The provided code 'http://terminology.hl7.org/CodeSystem/v2-0203#VN' was not found in the value set 'http://hl7.org/fhir/ValueSet/identifier-type|5.0.0-ballot'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "The provided code 'http://terminology.hl7.org/CodeSystem/v2-0203#VN' was not found in the value set 'http://hl7.org/fhir/ValueSet/identifier-type|5.0.0-ballot'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "IMP"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "2018-08-12"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "inpatient encounter"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use ValueSet http://terminology.hl7.org/ValueSet/v3-ActEncounterCode|2014-03-26"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to draft CodeSystem http://terminology.hl7.org/CodeSystem/v3-ActCode|2018-08-12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "10xx"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "invalid-code"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Unknown code '10xx' in the CodeSystem 'http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM' version '0.1.0'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "Unknown code '10xx' in the CodeSystem 'http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM' version '0.1.0'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "final"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/observation-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Final"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "10xx"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "not-in-vs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "The provided code 'http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM#10xx' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-codes|5.0.0-ballot'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "The provided code 'http://fhir.infoway-inforoute.ca/io/psca/CodeSystem/ICD9CM#10xx' was not found in the value set 'http://hl7.org/fhir/ValueSet/observation-codes|5.0.0-ballot'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "final"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/observation-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Final"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "StructureDefinition",
|
|
||||||
"id": "profile-procedure-with-slicing",
|
|
||||||
"url": "http://example.ca/fhir/StructureDefinition/profile-procedure-with-slicing",
|
|
||||||
"version": "0.11.0",
|
|
||||||
"name": "ProcedureProfile",
|
|
||||||
"title": "Procedure Profile",
|
|
||||||
"status": "active",
|
|
||||||
"date": "2022-10-15T12:00:00+00:00",
|
|
||||||
"publisher": "Example Organization",
|
|
||||||
"fhirVersion": "4.0.1",
|
|
||||||
"kind": "resource",
|
|
||||||
"abstract": false,
|
|
||||||
"type": "Procedure",
|
|
||||||
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Procedure",
|
|
||||||
"derivation": "constraint",
|
|
||||||
"differential": {
|
|
||||||
"element": [
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding",
|
|
||||||
"path": "Procedure.code.coding",
|
|
||||||
"slicing": {
|
|
||||||
"discriminator": [
|
|
||||||
{
|
|
||||||
"type": "pattern",
|
|
||||||
"path": "$this"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Discriminated by the bound value set",
|
|
||||||
"rules": "open"
|
|
||||||
},
|
|
||||||
"mustSupport": true,
|
|
||||||
"binding": {
|
|
||||||
"strength": "preferred",
|
|
||||||
"valueSet": "http://hl7.org/fhir/ValueSet/procedure-code"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding.display.extension:translation",
|
|
||||||
"path": "Procedure.code.coding.display.extension",
|
|
||||||
"sliceName": "translation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding.display.extension:translation.extension",
|
|
||||||
"path": "Procedure.code.coding.display.extension.extension",
|
|
||||||
"min": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding:absentOrUnknownProcedure",
|
|
||||||
"path": "Procedure.code.coding",
|
|
||||||
"sliceName": "absentOrUnknownProcedure",
|
|
||||||
"short": "Optional slice for representing a code for absent problem or for unknown procedure",
|
|
||||||
"definition": "Code representing the statement \"absent problem\" or the statement \"procedures unknown\"",
|
|
||||||
"mustSupport": true,
|
|
||||||
"binding": {
|
|
||||||
"extension": [
|
|
||||||
{
|
|
||||||
"url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName",
|
|
||||||
"valueString": "absentOrUnknownProcedure"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strength": "required",
|
|
||||||
"description": "A code to identify absent or unknown procedures",
|
|
||||||
"valueSet": "http://hl7.org/fhir/uv/ips/ValueSet/absent-or-unknown-procedures-uv-ips"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding:absentOrUnknownProcedure.display.extension:translation",
|
|
||||||
"path": "Procedure.code.coding.display.extension",
|
|
||||||
"sliceName": "translation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding:absentOrUnknownProcedure.display.extension:translation.extension",
|
|
||||||
"path": "Procedure.code.coding.display.extension.extension",
|
|
||||||
"min": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "StructureDefinition",
|
|
||||||
"id": "profile-procedure",
|
|
||||||
"url": "http://example.ca/fhir/StructureDefinition/profile-procedure",
|
|
||||||
"version": "0.11.0",
|
|
||||||
"name": "ProcedureProfile",
|
|
||||||
"title": "Procedure Profile",
|
|
||||||
"status": "active",
|
|
||||||
"date": "2022-10-15T12:00:00+00:00",
|
|
||||||
"publisher": "Example Organization",
|
|
||||||
"fhirVersion": "4.0.1",
|
|
||||||
"kind": "resource",
|
|
||||||
"abstract": false,
|
|
||||||
"type": "Procedure",
|
|
||||||
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Procedure",
|
|
||||||
"derivation": "constraint",
|
|
||||||
"differential": {
|
|
||||||
"element": [
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding",
|
|
||||||
"path": "Procedure.code.coding",
|
|
||||||
"slicing": {
|
|
||||||
"discriminator": [
|
|
||||||
{
|
|
||||||
"type": "pattern",
|
|
||||||
"path": "$this"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Discriminated by the bound value set",
|
|
||||||
"rules": "open"
|
|
||||||
},
|
|
||||||
"mustSupport": true,
|
|
||||||
"binding": {
|
|
||||||
"strength": "preferred",
|
|
||||||
"valueSet": "http://hl7.org/fhir/ValueSet/procedure-code"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding.display.extension:translation",
|
|
||||||
"path": "Procedure.code.coding.display.extension",
|
|
||||||
"sliceName": "translation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Procedure.code.coding.display.extension:translation.extension",
|
|
||||||
"path": "Procedure.code.coding.display.extension.extension",
|
|
||||||
"min": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "no-procedure-info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "1.1.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "No information about past history of procedures"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use CodeSystem http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips|1.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "completed"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/event-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Completed"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use CodeSystem http://hl7.org/fhir/event-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to experimental CodeSystem http://hl7.org/fhir/event-status|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "xx417005"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://snomed.info/sct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "invalid-code"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Unknown code 'xx417005' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/32506021000036107/version/20241031'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "Unknown code 'xx417005' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/32506021000036107/version/20241031'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "417005"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://snomed.info/sct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "http://snomed.info/sct/32506021000036107/version/20241031"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Hospital re-admission"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "no-procedure-info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "1.1.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "No information about past history of procedures"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use CodeSystem http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips|1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to trial-use ValueSet http://hl7.org/fhir/uv/ips/ValueSet/absent-or-unknown-procedures-uv-ips|1.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "final"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/procedure-status"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "5.0.0-ballot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Final"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "no-procedure-info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "not-in-vs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "The provided code 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips#no-procedure-info' was not found in the value set 'http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "The provided code 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips#no-procedure-info' was not found in the value set 'http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "xx417005"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://snomed.info/sct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "not-in-vs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "The provided code 'http://snomed.info/sct#xx417005' was not found in the value set 'http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "error",
|
|
||||||
"code": "code-invalid",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "invalid-code"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Unknown code 'xx417005' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/32506021000036107/version/20241031'"
|
|
||||||
},
|
|
||||||
"location": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"expression": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "message",
|
|
||||||
"valueString": "Unknown code 'xx417005' in the CodeSystem 'http://snomed.info/sct' version 'http://snomed.info/sct/32506021000036107/version/20241031'; The provided code 'http://snomed.info/sct#xx417005' was not found in the value set 'http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot'"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "Parameters",
|
|
||||||
"parameter": [
|
|
||||||
{
|
|
||||||
"name": "result",
|
|
||||||
"valueBoolean": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "code",
|
|
||||||
"valueCode": "417005"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "system",
|
|
||||||
"valueUri": "http://snomed.info/sct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "version",
|
|
||||||
"valueString": "http://snomed.info/sct/32506021000036107/version/20241031"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "display",
|
|
||||||
"valueString": "Hospital re-admission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "issues",
|
|
||||||
"resource": {
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to draft ValueSet http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "business-rule",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
|
||||||
"code": "status-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"text": "Reference to experimental ValueSet http://hl7.org/fhir/ValueSet/procedure-code|5.0.0-ballot"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
package ca.uhn.fhir.test.utilities.validation;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
|
||||||
import ca.uhn.fhir.rest.param.UriParam;
|
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.util.ClasspathUtil;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
|
||||||
import org.hl7.fhir.instance.model.api.IDomainResource;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface IValidationProviders {
|
|
||||||
String CODE_SYSTEM = "http://code.system/url";
|
|
||||||
String CODE_SYSTEM_VERSION = "1.0.0";
|
|
||||||
String CODE_SYSTEM_NAME = "Test Code System";
|
|
||||||
String CODE = "CODE";
|
|
||||||
String VALUE_SET_URL = "http://value.set/url";
|
|
||||||
String DISPLAY = "Explanation for code TestCode.";
|
|
||||||
String LANGUAGE = "en";
|
|
||||||
String ERROR_MESSAGE = "This is an error message";
|
|
||||||
|
|
||||||
interface IMyValidationProvider extends IResourceProvider {
|
|
||||||
void addException(String theOperation, String theUrl, String theCode, Exception theException);
|
|
||||||
<P extends IBaseParameters> void addTerminologyResponse(String theOperation, String theUrl, String theCode, P theReturnParams);
|
|
||||||
IBaseParameters addTerminologyResponse(String theOperation, String theUrl, String theCode, FhirContext theFhirContext, String theTerminologyResponseFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class MyValidationProvider<T extends IDomainResource> implements IMyValidationProvider {
|
|
||||||
private final Map<String, Exception> myExceptionMap = new HashMap<>();
|
|
||||||
private boolean myShouldThrowExceptionForResourceNotFound = true;
|
|
||||||
private final Map<String, IBaseParameters> myTerminologyResponseMap = new HashMap<>();
|
|
||||||
private final Map<String, T> myTerminologyResourceMap = new HashMap<>();
|
|
||||||
|
|
||||||
static String getInputKey(String theOperation, String theUrl, String theCode) {
|
|
||||||
return theOperation + "-" + theUrl + "#" + theCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShouldThrowExceptionForResourceNotFound(boolean theShouldThrowExceptionForResourceNotFound) {
|
|
||||||
myShouldThrowExceptionForResourceNotFound = theShouldThrowExceptionForResourceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addException(String theOperation, String theUrl, String theCode, Exception theException) {
|
|
||||||
String inputKey = getInputKey(theOperation, theUrl, theCode);
|
|
||||||
myExceptionMap.put(inputKey, theException);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract Class<? extends IBaseParameters> getParameterType();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <P extends IBaseParameters> void addTerminologyResponse(String theOperation, String theUrl, String theCode, P theReturnParams) {
|
|
||||||
myTerminologyResponseMap.put(getInputKey(theOperation, theUrl, theCode), theReturnParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBaseParameters addTerminologyResponse(String theOperation, String theUrl, String theCode, FhirContext theFhirContext, String theTerminologyResponseFile) {
|
|
||||||
IBaseParameters responseParams = ClasspathUtil.loadResource(theFhirContext, getParameterType(), theTerminologyResponseFile);
|
|
||||||
addTerminologyResponse(theOperation, theUrl, theCode, responseParams);
|
|
||||||
return responseParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addTerminologyResource(String theUrl, T theResource) {
|
|
||||||
myTerminologyResourceMap.put(theUrl, theResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract T addTerminologyResource(String theUrl);
|
|
||||||
|
|
||||||
protected IBaseParameters getTerminologyResponse(String theOperation, String theUrl, String theCode) throws Exception {
|
|
||||||
String inputKey = getInputKey(theOperation, theUrl, theCode);
|
|
||||||
if (myExceptionMap.containsKey(inputKey)) {
|
|
||||||
throw myExceptionMap.get(inputKey);
|
|
||||||
}
|
|
||||||
IBaseParameters params = myTerminologyResponseMap.get(inputKey);
|
|
||||||
if (params == null) {
|
|
||||||
throw new IllegalStateException("Test setup incomplete. Missing return params for " + inputKey);
|
|
||||||
}
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected T getTerminologyResource(UriParam theUrlParam) {
|
|
||||||
if (theUrlParam.isEmpty()) {
|
|
||||||
throw new IllegalStateException("CodeSystem url should not be null.");
|
|
||||||
}
|
|
||||||
String urlValue = theUrlParam.getValue();
|
|
||||||
if (!myTerminologyResourceMap.containsKey(urlValue) && myShouldThrowExceptionForResourceNotFound) {
|
|
||||||
throw new IllegalStateException("Test setup incomplete. CodeSystem not found " + urlValue);
|
|
||||||
}
|
|
||||||
return myTerminologyResourceMap.get(urlValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Search
|
|
||||||
public List<T> find(@RequiredParam(name = "url") UriParam theUrlParam) {
|
|
||||||
T resource = getTerminologyResource(theUrlParam);
|
|
||||||
return resource != null ? List.of(resource) : List.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMyLookupCodeProvider extends IResourceProvider {
|
|
||||||
void setLookupCodeResult(IValidationSupport.LookupCodeResult theLookupCodeResult);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
package ca.uhn.fhir.test.utilities.validation;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
|
||||||
import org.hl7.fhir.dstu3.model.CodeType;
|
|
||||||
import org.hl7.fhir.dstu3.model.Coding;
|
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface IValidationProvidersDstu3 {
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
class MyCodeSystemProviderDstu3 extends IValidationProviders.MyValidationProvider<CodeSystem> {
|
|
||||||
@Operation(name = "$validate-code", idempotent = true, returnParameters = {
|
|
||||||
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
|
||||||
@OperationParam(name = "message", type = StringType.class),
|
|
||||||
@OperationParam(name = "display", type = StringType.class)
|
|
||||||
})
|
|
||||||
public IBaseParameters validateCode(
|
|
||||||
HttpServletRequest theServletRequest,
|
|
||||||
@IdParam(optional = true) IdType theId,
|
|
||||||
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
|
|
||||||
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
|
||||||
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay
|
|
||||||
) throws Exception {
|
|
||||||
String url = theCodeSystemUrl != null ? theCodeSystemUrl.getValue() : null;
|
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
|
||||||
return getTerminologyResponse("$validate-code", url, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(name = "$lookup", idempotent = true, returnParameters= {
|
|
||||||
@OperationParam(name = "name", type = StringType.class, min = 1),
|
|
||||||
@OperationParam(name = "version", type = StringType.class),
|
|
||||||
@OperationParam(name = "display", type = StringType.class, min = 1),
|
|
||||||
@OperationParam(name = "abstract", type = BooleanType.class, min = 1),
|
|
||||||
@OperationParam(name = "property", type = StringType.class, min = 0, max = OperationParam.MAX_UNLIMITED)
|
|
||||||
})
|
|
||||||
public IBaseParameters lookup(
|
|
||||||
HttpServletRequest theServletRequest,
|
|
||||||
@OperationParam(name = "code", max = 1) CodeType theCode,
|
|
||||||
@OperationParam(name = "system",max = 1) UriType theSystem,
|
|
||||||
@OperationParam(name = "coding", max = 1) Coding theCoding,
|
|
||||||
@OperationParam(name = "version", max = 1) StringType theVersion,
|
|
||||||
@OperationParam(name = "displayLanguage", max = 1) CodeType theDisplayLanguage,
|
|
||||||
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<CodeType> thePropertyNames,
|
|
||||||
RequestDetails theRequestDetails
|
|
||||||
) throws Exception {
|
|
||||||
String url = theSystem != null ? theSystem.getValue() : null;
|
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
|
||||||
return getTerminologyResponse("$lookup", url, code);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
|
||||||
return CodeSystem.class;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
Class<Parameters> getParameterType() {
|
|
||||||
return Parameters.class;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public CodeSystem addTerminologyResource(String theUrl) {
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
|
||||||
codeSystem.setId(theUrl.substring(0, theUrl.lastIndexOf("/")));
|
|
||||||
codeSystem.setUrl(theUrl);
|
|
||||||
addTerminologyResource(theUrl, codeSystem);
|
|
||||||
return codeSystem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
class MyValueSetProviderDstu3 extends IValidationProviders.MyValidationProvider<ValueSet> {
|
|
||||||
@Operation(name = "$validate-code", idempotent = true, returnParameters = {
|
|
||||||
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
|
||||||
@OperationParam(name = "message", type = StringType.class),
|
|
||||||
@OperationParam(name = "display", type = StringType.class)
|
|
||||||
})
|
|
||||||
public IBaseParameters validateCode(
|
|
||||||
HttpServletRequest theServletRequest,
|
|
||||||
@IdParam(optional = true) IdType theId,
|
|
||||||
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
|
|
||||||
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
|
||||||
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
|
|
||||||
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
|
|
||||||
@OperationParam(name = "valueSet") ValueSet theValueSet
|
|
||||||
) throws Exception {
|
|
||||||
String url = theValueSetUrl != null ? theValueSetUrl.getValue() : null;
|
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
|
||||||
return getTerminologyResponse("$validate-code", url, code);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
|
||||||
return ValueSet.class;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
Class<Parameters> getParameterType() {
|
|
||||||
return Parameters.class;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public ValueSet addTerminologyResource(String theUrl) {
|
|
||||||
ValueSet valueSet = new ValueSet();
|
|
||||||
valueSet.setId(theUrl.substring(0, theUrl.lastIndexOf("/")));
|
|
||||||
valueSet.setUrl(theUrl);
|
|
||||||
addTerminologyResource(theUrl, valueSet);
|
|
||||||
return valueSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -190,7 +190,7 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport {
|
||||||
return new CodeValidationResult()
|
return new CodeValidationResult()
|
||||||
.setSeverity(IssueSeverity.ERROR)
|
.setSeverity(IssueSeverity.ERROR)
|
||||||
.setMessage(theMessage)
|
.setMessage(theMessage)
|
||||||
.setIssues(Collections.singletonList(new CodeValidationIssue(
|
.setCodeValidationIssues(Collections.singletonList(new CodeValidationIssue(
|
||||||
theMessage,
|
theMessage,
|
||||||
IssueSeverity.ERROR,
|
IssueSeverity.ERROR,
|
||||||
CodeValidationIssueCode.INVALID,
|
CodeValidationIssueCode.INVALID,
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.r5.model.CanonicalType;
|
import org.hl7.fhir.r5.model.CanonicalType;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.Enumerations;
|
import org.hl7.fhir.r5.model.Enumerations;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -257,7 +258,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
theValidationSupportContext, theValueSet, theCodeSystemUrlAndVersion, theCode);
|
theValidationSupportContext, theValueSet, theCodeSystemUrlAndVersion, theCode);
|
||||||
} catch (ExpansionCouldNotBeCompletedInternallyException e) {
|
} catch (ExpansionCouldNotBeCompletedInternallyException e) {
|
||||||
CodeValidationResult codeValidationResult = new CodeValidationResult();
|
CodeValidationResult codeValidationResult = new CodeValidationResult();
|
||||||
codeValidationResult.setSeverity(IssueSeverity.ERROR);
|
codeValidationResult.setSeverityCode("error");
|
||||||
|
|
||||||
String msg = "Failed to expand ValueSet '" + vsUrl + "' (in-memory). Could not validate code "
|
String msg = "Failed to expand ValueSet '" + vsUrl + "' (in-memory). Could not validate code "
|
||||||
+ theCodeSystemUrlAndVersion + "#" + theCode;
|
+ theCodeSystemUrlAndVersion + "#" + theCode;
|
||||||
|
@ -266,7 +267,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
}
|
}
|
||||||
|
|
||||||
codeValidationResult.setMessage(msg);
|
codeValidationResult.setMessage(msg);
|
||||||
codeValidationResult.addIssue(e.getCodeValidationIssue());
|
codeValidationResult.addCodeValidationIssue(e.getCodeValidationIssue());
|
||||||
return codeValidationResult;
|
return codeValidationResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,18 +551,18 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
if (valueSetResult != null) {
|
if (valueSetResult != null) {
|
||||||
codeValidationResult = valueSetResult;
|
codeValidationResult = valueSetResult;
|
||||||
} else {
|
} else {
|
||||||
IValidationSupport.IssueSeverity severity;
|
ValidationMessage.IssueSeverity severity;
|
||||||
String message;
|
String message;
|
||||||
CodeValidationIssueCode issueCode = CodeValidationIssueCode.CODE_INVALID;
|
CodeValidationIssueCode issueCode = CodeValidationIssueCode.CODE_INVALID;
|
||||||
CodeValidationIssueCoding issueCoding = CodeValidationIssueCoding.INVALID_CODE;
|
CodeValidationIssueCoding issueCoding = CodeValidationIssueCoding.INVALID_CODE;
|
||||||
if ("fragment".equals(codeSystemResourceContentMode)) {
|
if ("fragment".equals(codeSystemResourceContentMode)) {
|
||||||
severity = IValidationSupport.IssueSeverity.WARNING;
|
severity = ValidationMessage.IssueSeverity.WARNING;
|
||||||
message = "Unknown code in fragment CodeSystem '"
|
message = "Unknown code in fragment CodeSystem '"
|
||||||
+ getFormattedCodeSystemAndCodeForMessage(
|
+ getFormattedCodeSystemAndCodeForMessage(
|
||||||
theCodeSystemUrlAndVersionToValidate, theCodeToValidate)
|
theCodeSystemUrlAndVersionToValidate, theCodeToValidate)
|
||||||
+ "'";
|
+ "'";
|
||||||
} else {
|
} else {
|
||||||
severity = IValidationSupport.IssueSeverity.ERROR;
|
severity = ValidationMessage.IssueSeverity.ERROR;
|
||||||
message = "Unknown code '"
|
message = "Unknown code '"
|
||||||
+ getFormattedCodeSystemAndCodeForMessage(
|
+ getFormattedCodeSystemAndCodeForMessage(
|
||||||
theCodeSystemUrlAndVersionToValidate, theCodeToValidate)
|
theCodeSystemUrlAndVersionToValidate, theCodeToValidate)
|
||||||
|
@ -573,9 +574,10 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
}
|
}
|
||||||
|
|
||||||
codeValidationResult = new CodeValidationResult()
|
codeValidationResult = new CodeValidationResult()
|
||||||
.setSeverity(severity)
|
.setSeverityCode(severity.toCode())
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.addIssue(new CodeValidationIssue(message, severity, issueCode, issueCoding));
|
.addCodeValidationIssue(new CodeValidationIssue(
|
||||||
|
message, getIssueSeverityFromCodeValidationIssue(severity), issueCode, issueCoding));
|
||||||
}
|
}
|
||||||
|
|
||||||
return codeValidationResult;
|
return codeValidationResult;
|
||||||
|
@ -587,6 +589,19 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
+ theCodeToValidate;
|
+ theCodeToValidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IValidationSupport.IssueSeverity getIssueSeverityFromCodeValidationIssue(
|
||||||
|
ValidationMessage.IssueSeverity theSeverity) {
|
||||||
|
switch (theSeverity) {
|
||||||
|
case ERROR:
|
||||||
|
return IValidationSupport.IssueSeverity.ERROR;
|
||||||
|
case WARNING:
|
||||||
|
return IValidationSupport.IssueSeverity.WARNING;
|
||||||
|
case INFORMATION:
|
||||||
|
return IValidationSupport.IssueSeverity.INFORMATION;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private CodeValidationResult findCodeInExpansion(
|
private CodeValidationResult findCodeInExpansion(
|
||||||
String theCodeToValidate,
|
String theCodeToValidate,
|
||||||
String theDisplayToValidate,
|
String theDisplayToValidate,
|
||||||
|
@ -1108,8 +1123,8 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
new CodeValidationIssue(
|
new CodeValidationIssue(
|
||||||
theMessage,
|
theMessage,
|
||||||
IssueSeverity.ERROR,
|
IssueSeverity.ERROR,
|
||||||
CodeValidationIssueCode.INVALID,
|
CodeValidationIssueCode.OTHER,
|
||||||
CodeValidationIssueCoding.VS_INVALID));
|
CodeValidationIssueCoding.OTHER));
|
||||||
}
|
}
|
||||||
for (org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent next :
|
for (org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent next :
|
||||||
subExpansion.getExpansion().getContains()) {
|
subExpansion.getExpansion().getContains()) {
|
||||||
|
@ -1361,7 +1376,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
.setCodeSystemVersion(theCodeSystemVersion)
|
.setCodeSystemVersion(theCodeSystemVersion)
|
||||||
.setDisplay(theExpectedDisplay);
|
.setDisplay(theExpectedDisplay);
|
||||||
if (issueSeverity != null) {
|
if (issueSeverity != null) {
|
||||||
codeValidationResult.setIssues(Collections.singletonList(new CodeValidationIssue(
|
codeValidationResult.setCodeValidationIssues(Collections.singletonList(new CodeValidationIssue(
|
||||||
message,
|
message,
|
||||||
theIssueSeverityForCodeDisplayMismatch,
|
theIssueSeverityForCodeDisplayMismatch,
|
||||||
CodeValidationIssueCode.INVALID,
|
CodeValidationIssueCode.INVALID,
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.Base;
|
import org.hl7.fhir.r4.model.Base;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
import org.hl7.fhir.r4.model.CodeType;
|
import org.hl7.fhir.r4.model.CodeType;
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
|
@ -632,7 +631,7 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup
|
||||||
return new CodeValidationResult()
|
return new CodeValidationResult()
|
||||||
.setSeverity(severity)
|
.setSeverity(severity)
|
||||||
.setMessage(theMessage)
|
.setMessage(theMessage)
|
||||||
.addIssue(new CodeValidationIssue(
|
.addCodeValidationIssue(new CodeValidationIssue(
|
||||||
theMessage, severity, theIssueCode, CodeValidationIssueCoding.INVALID_CODE));
|
theMessage, severity, theIssueCode, CodeValidationIssueCoding.INVALID_CODE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,13 +680,13 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup
|
||||||
createCodeValidationIssues(
|
createCodeValidationIssues(
|
||||||
(IBaseOperationOutcome) issuesValue.get(),
|
(IBaseOperationOutcome) issuesValue.get(),
|
||||||
fhirContext.getVersion().getVersion())
|
fhirContext.getVersion().getVersion())
|
||||||
.ifPresent(i -> i.forEach(result::addIssue));
|
.ifPresent(i -> i.forEach(result::addCodeValidationIssue));
|
||||||
} else {
|
} else {
|
||||||
// create a validation issue out of the message
|
// create a validation issue out of the message
|
||||||
// this is a workaround to overcome an issue in the FHIR Validator library
|
// this is a workaround to overcome an issue in the FHIR Validator library
|
||||||
// where ValueSet bindings are only reading issues but not messages
|
// where ValueSet bindings are only reading issues but not messages
|
||||||
// @see https://github.com/hapifhir/org.hl7.fhir.core/issues/1766
|
// @see https://github.com/hapifhir/org.hl7.fhir.core/issues/1766
|
||||||
result.addIssue(createCodeValidationIssue(result.getMessage()));
|
result.addCodeValidationIssue(createCodeValidationIssue(result.getMessage()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -718,42 +717,23 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup
|
||||||
|
|
||||||
private static Collection<CodeValidationIssue> createCodeValidationIssuesR4(OperationOutcome theOperationOutcome) {
|
private static Collection<CodeValidationIssue> createCodeValidationIssuesR4(OperationOutcome theOperationOutcome) {
|
||||||
return theOperationOutcome.getIssue().stream()
|
return theOperationOutcome.getIssue().stream()
|
||||||
.map(issueComponent -> {
|
.map(issueComponent ->
|
||||||
String diagnostics = issueComponent.getDiagnostics();
|
createCodeValidationIssue(issueComponent.getDetails().getText()))
|
||||||
IssueSeverity issueSeverity =
|
|
||||||
IssueSeverity.fromCode(issueComponent.getSeverity().toCode());
|
|
||||||
String issueTypeCode = issueComponent.getCode().toCode();
|
|
||||||
CodeableConcept details = issueComponent.getDetails();
|
|
||||||
CodeValidationIssue issue = new CodeValidationIssue(diagnostics, issueSeverity, issueTypeCode);
|
|
||||||
CodeValidationIssueDetails issueDetails = new CodeValidationIssueDetails(details.getText());
|
|
||||||
details.getCoding().forEach(coding -> issueDetails.addCoding(coding.getSystem(), coding.getCode()));
|
|
||||||
issue.setDetails(issueDetails);
|
|
||||||
return issue;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<CodeValidationIssue> createCodeValidationIssuesDstu3(
|
private static Collection<CodeValidationIssue> createCodeValidationIssuesDstu3(
|
||||||
org.hl7.fhir.dstu3.model.OperationOutcome theOperationOutcome) {
|
org.hl7.fhir.dstu3.model.OperationOutcome theOperationOutcome) {
|
||||||
return theOperationOutcome.getIssue().stream()
|
return theOperationOutcome.getIssue().stream()
|
||||||
.map(issueComponent -> {
|
.map(issueComponent ->
|
||||||
String diagnostics = issueComponent.getDiagnostics();
|
createCodeValidationIssue(issueComponent.getDetails().getText()))
|
||||||
IssueSeverity issueSeverity =
|
|
||||||
IssueSeverity.fromCode(issueComponent.getSeverity().toCode());
|
|
||||||
String issueTypeCode = issueComponent.getCode().toCode();
|
|
||||||
org.hl7.fhir.dstu3.model.CodeableConcept details = issueComponent.getDetails();
|
|
||||||
CodeValidationIssue issue = new CodeValidationIssue(diagnostics, issueSeverity, issueTypeCode);
|
|
||||||
CodeValidationIssueDetails issueDetails = new CodeValidationIssueDetails(details.getText());
|
|
||||||
details.getCoding().forEach(coding -> issueDetails.addCoding(coding.getSystem(), coding.getCode()));
|
|
||||||
issue.setDetails(issueDetails);
|
|
||||||
return issue;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CodeValidationIssue createCodeValidationIssue(String theMessage) {
|
private static CodeValidationIssue createCodeValidationIssue(String theMessage) {
|
||||||
return new CodeValidationIssue(
|
return new CodeValidationIssue(
|
||||||
theMessage,
|
theMessage,
|
||||||
|
// assume issue type is OperationOutcome.IssueType#CODEINVALID as it is the only match
|
||||||
IssueSeverity.ERROR,
|
IssueSeverity.ERROR,
|
||||||
CodeValidationIssueCode.INVALID,
|
CodeValidationIssueCode.INVALID,
|
||||||
CodeValidationIssueCoding.INVALID_CODE);
|
CodeValidationIssueCoding.INVALID_CODE);
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
result.setSeverity(null);
|
result.setSeverity(null);
|
||||||
result.setMessage(null);
|
result.setMessage(null);
|
||||||
} else {
|
} else {
|
||||||
result.addIssue(new CodeValidationIssue(
|
result.addCodeValidationIssue(new CodeValidationIssue(
|
||||||
theMessage,
|
theMessage,
|
||||||
myNonExistentCodeSystemSeverity,
|
myNonExistentCodeSystemSeverity,
|
||||||
CodeValidationIssueCode.NOT_FOUND,
|
CodeValidationIssueCode.NOT_FOUND,
|
||||||
|
|
|
@ -11,17 +11,6 @@ public final class ValidationSupportUtils {
|
||||||
|
|
||||||
private ValidationSupportUtils() {}
|
private ValidationSupportUtils() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method extracts a code system that can be (potentially) associated with a code when
|
|
||||||
* performing validation against a ValueSet. This method was created for internal purposes.
|
|
||||||
* Please use this method with care because it will only cover some
|
|
||||||
* use-cases (e.g. standard bindings) while for others it may not return correct results or return null.
|
|
||||||
* An incorrect result could be considered if the resource declares a code with a system, and you're calling
|
|
||||||
* this method to check a binding against a ValueSet that has nothing to do with that system.
|
|
||||||
* @param theValueSet the valueSet
|
|
||||||
* @param theCode the code
|
|
||||||
* @return the system which can be associated with the code
|
|
||||||
*/
|
|
||||||
public static String extractCodeSystemForCode(IBaseResource theValueSet, String theCode) {
|
public static String extractCodeSystemForCode(IBaseResource theValueSet, String theCode) {
|
||||||
if (theValueSet instanceof org.hl7.fhir.dstu3.model.ValueSet) {
|
if (theValueSet instanceof org.hl7.fhir.dstu3.model.ValueSet) {
|
||||||
return extractCodeSystemForCodeDSTU3((org.hl7.fhir.dstu3.model.ValueSet) theValueSet, theCode);
|
return extractCodeSystemForCodeDSTU3((org.hl7.fhir.dstu3.model.ValueSet) theValueSet, theCode);
|
||||||
|
|
|
@ -62,7 +62,6 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static ca.uhn.fhir.context.support.IValidationSupport.CodeValidationIssueCoding.INVALID_DISPLAY;
|
|
||||||
import static java.util.stream.Collectors.collectingAndThen;
|
import static java.util.stream.Collectors.collectingAndThen;
|
||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
@ -297,7 +296,7 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo
|
||||||
theResult.getCodeSystemVersion(),
|
theResult.getCodeSystemVersion(),
|
||||||
conceptDefinitionComponent,
|
conceptDefinitionComponent,
|
||||||
display,
|
display,
|
||||||
getIssuesForCodeValidation(theResult.getIssues()));
|
getIssuesForCodeValidation(theResult.getCodeValidationIssues()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retVal == null) {
|
if (retVal == null) {
|
||||||
|
@ -308,36 +307,73 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<OperationOutcome.OperationOutcomeIssueComponent> getIssuesForCodeValidation(
|
private List<OperationOutcome.OperationOutcomeIssueComponent> getIssuesForCodeValidation(
|
||||||
List<IValidationSupport.CodeValidationIssue> theIssues) {
|
List<IValidationSupport.CodeValidationIssue> codeValidationIssues) {
|
||||||
List<OperationOutcome.OperationOutcomeIssueComponent> issueComponents = new ArrayList<>();
|
List<OperationOutcome.OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||||
|
|
||||||
for (IValidationSupport.CodeValidationIssue issue : theIssues) {
|
for (IValidationSupport.CodeValidationIssue codeValidationIssue : codeValidationIssues) {
|
||||||
OperationOutcome.IssueSeverity severity =
|
|
||||||
OperationOutcome.IssueSeverity.fromCode(issue.getSeverity().getCode());
|
|
||||||
OperationOutcome.IssueType issueType =
|
|
||||||
OperationOutcome.IssueType.fromCode(issue.getType().getCode());
|
|
||||||
String diagnostics = issue.getDiagnostics();
|
|
||||||
|
|
||||||
IValidationSupport.CodeValidationIssueDetails details = issue.getDetails();
|
CodeableConcept codeableConcept = new CodeableConcept().setText(codeValidationIssue.getMessage());
|
||||||
CodeableConcept codeableConcept = new CodeableConcept().setText(details.getText());
|
codeableConcept.addCoding(
|
||||||
details.getCodings().forEach(detailCoding -> codeableConcept
|
"http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||||
.addCoding()
|
getIssueCodingFromCodeValidationIssue(codeValidationIssue),
|
||||||
.setSystem(detailCoding.getSystem())
|
null);
|
||||||
.setCode(detailCoding.getCode()));
|
|
||||||
|
|
||||||
OperationOutcome.OperationOutcomeIssueComponent issueComponent =
|
OperationOutcome.OperationOutcomeIssueComponent issue =
|
||||||
new OperationOutcome.OperationOutcomeIssueComponent()
|
new OperationOutcome.OperationOutcomeIssueComponent()
|
||||||
.setSeverity(severity)
|
.setSeverity(getIssueSeverityFromCodeValidationIssue(codeValidationIssue))
|
||||||
.setCode(issueType)
|
.setCode(getIssueTypeFromCodeValidationIssue(codeValidationIssue))
|
||||||
.setDetails(codeableConcept)
|
.setDetails(codeableConcept);
|
||||||
.setDiagnostics(diagnostics);
|
issue.getDetails().setText(codeValidationIssue.getMessage());
|
||||||
issueComponent
|
issue.addExtension()
|
||||||
.addExtension()
|
|
||||||
.setUrl("http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id")
|
.setUrl("http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id")
|
||||||
.setValue(new StringType("Terminology_PassThrough_TX_Message"));
|
.setValue(new StringType("Terminology_PassThrough_TX_Message"));
|
||||||
issueComponents.add(issueComponent);
|
issues.add(issue);
|
||||||
}
|
}
|
||||||
return issueComponents;
|
return issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getIssueCodingFromCodeValidationIssue(IValidationSupport.CodeValidationIssue codeValidationIssue) {
|
||||||
|
switch (codeValidationIssue.getCoding()) {
|
||||||
|
case VS_INVALID:
|
||||||
|
return "vs-invalid";
|
||||||
|
case NOT_FOUND:
|
||||||
|
return "not-found";
|
||||||
|
case NOT_IN_VS:
|
||||||
|
return "not-in-vs";
|
||||||
|
case INVALID_CODE:
|
||||||
|
return "invalid-code";
|
||||||
|
case INVALID_DISPLAY:
|
||||||
|
return "invalid-display";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationOutcome.IssueType getIssueTypeFromCodeValidationIssue(
|
||||||
|
IValidationSupport.CodeValidationIssue codeValidationIssue) {
|
||||||
|
switch (codeValidationIssue.getCode()) {
|
||||||
|
case NOT_FOUND:
|
||||||
|
return OperationOutcome.IssueType.NOTFOUND;
|
||||||
|
case CODE_INVALID:
|
||||||
|
return OperationOutcome.IssueType.CODEINVALID;
|
||||||
|
case INVALID:
|
||||||
|
return OperationOutcome.IssueType.INVALID;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationOutcome.IssueSeverity getIssueSeverityFromCodeValidationIssue(
|
||||||
|
IValidationSupport.CodeValidationIssue codeValidationIssue) {
|
||||||
|
switch (codeValidationIssue.getSeverity()) {
|
||||||
|
case FATAL:
|
||||||
|
return OperationOutcome.IssueSeverity.FATAL;
|
||||||
|
case ERROR:
|
||||||
|
return OperationOutcome.IssueSeverity.ERROR;
|
||||||
|
case WARNING:
|
||||||
|
return OperationOutcome.IssueSeverity.WARNING;
|
||||||
|
case INFORMATION:
|
||||||
|
return OperationOutcome.IssueSeverity.INFORMATION;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -815,22 +851,25 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo
|
||||||
.getRootValidationSupport()
|
.getRootValidationSupport()
|
||||||
.validateCodeInValueSet(
|
.validateCodeInValueSet(
|
||||||
myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, theValueSet);
|
myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, theValueSet);
|
||||||
if (result != null && theSystem != null) {
|
if (result != null) {
|
||||||
/* We got a value set result, which could be successful, or could contain errors/warnings. The code
|
/* We got a value set result, which could be successful, or could contain errors/warnings. The code
|
||||||
might also be invalid in the code system, so we will check that as well and add those issues
|
might also be invalid in the code system, so we will check that as well and add those issues
|
||||||
to our result.
|
to our result.
|
||||||
*/
|
*/
|
||||||
IValidationSupport.CodeValidationResult codeSystemResult =
|
IValidationSupport.CodeValidationResult codeSystemResult =
|
||||||
validateCodeInCodeSystem(theValidationOptions, theSystem, theCode, theDisplay);
|
validateCodeInCodeSystem(theValidationOptions, theSystem, theCode, theDisplay);
|
||||||
final boolean valueSetResultContainsInvalidDisplay = result.getIssues().stream()
|
final boolean valueSetResultContainsInvalidDisplay = result.getCodeValidationIssues().stream()
|
||||||
.anyMatch(VersionSpecificWorkerContextWrapper::hasInvalidDisplayDetailCode);
|
.anyMatch(codeValidationIssue -> codeValidationIssue.getCoding()
|
||||||
|
== IValidationSupport.CodeValidationIssueCoding.INVALID_DISPLAY);
|
||||||
if (codeSystemResult != null) {
|
if (codeSystemResult != null) {
|
||||||
for (IValidationSupport.CodeValidationIssue codeValidationIssue : codeSystemResult.getIssues()) {
|
for (IValidationSupport.CodeValidationIssue codeValidationIssue :
|
||||||
|
codeSystemResult.getCodeValidationIssues()) {
|
||||||
/* Value set validation should already have checked the display name. If we get INVALID_DISPLAY
|
/* Value set validation should already have checked the display name. If we get INVALID_DISPLAY
|
||||||
issues from code system validation, they will only repeat what was already caught.
|
issues from code system validation, they will only repeat what was already caught.
|
||||||
*/
|
*/
|
||||||
if (!hasInvalidDisplayDetailCode(codeValidationIssue) || !valueSetResultContainsInvalidDisplay) {
|
if (codeValidationIssue.getCoding() != IValidationSupport.CodeValidationIssueCoding.INVALID_DISPLAY
|
||||||
result.addIssue(codeValidationIssue);
|
|| !valueSetResultContainsInvalidDisplay) {
|
||||||
|
result.addCodeValidationIssue(codeValidationIssue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -838,10 +877,6 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasInvalidDisplayDetailCode(IValidationSupport.CodeValidationIssue theIssue) {
|
|
||||||
return theIssue.hasIssueDetailCode(INVALID_DISPLAY.getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
private IValidationSupport.CodeValidationResult validateCodeInCodeSystem(
|
private IValidationSupport.CodeValidationResult validateCodeInCodeSystem(
|
||||||
ConceptValidationOptions theValidationOptions, String theSystem, String theCode, String theDisplay) {
|
ConceptValidationOptions theValidationOptions, String theSystem, String theCode, String theDisplay) {
|
||||||
return myValidationSupportContext
|
return myValidationSupportContext
|
||||||
|
|
|
@ -9,7 +9,6 @@ import ca.uhn.fhir.context.support.IValidationSupport.LookupCodeResult;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport.StringConceptProperty;
|
import ca.uhn.fhir.context.support.IValidationSupport.StringConceptProperty;
|
||||||
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -22,12 +21,12 @@ import static ca.uhn.fhir.context.support.IValidationSupport.TYPE_GROUP;
|
||||||
import static ca.uhn.fhir.context.support.IValidationSupport.TYPE_STRING;
|
import static ca.uhn.fhir.context.support.IValidationSupport.TYPE_STRING;
|
||||||
import static java.util.stream.IntStream.range;
|
import static java.util.stream.IntStream.range;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM_NAME;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_NAME;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.DISPLAY;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.DISPLAY;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.LANGUAGE;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.LANGUAGE;
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.createConceptProperty;
|
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.createConceptProperty;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
@ -190,6 +189,8 @@ public interface ILookupCodeTest {
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
assertNotNull(outcome);
|
assertNotNull(outcome);
|
||||||
|
assertEquals(theRequest.getCode(), getLookupCodeProvider().getCode());
|
||||||
|
assertEquals(theRequest.getSystem(), getLookupCodeProvider().getSystem());
|
||||||
assertEquals(theExpectedResult.isFound(), outcome.isFound());
|
assertEquals(theExpectedResult.isFound(), outcome.isFound());
|
||||||
assertEquals(theExpectedResult.getErrorMessage(), outcome.getErrorMessage());
|
assertEquals(theExpectedResult.getErrorMessage(), outcome.getErrorMessage());
|
||||||
assertEquals(theExpectedResult.getCodeSystemDisplayName(), outcome.getCodeSystemDisplayName());
|
assertEquals(theExpectedResult.getCodeSystemDisplayName(), outcome.getCodeSystemDisplayName());
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.hl7.fhir.common.hapi.validation;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport.LookupCodeResult;
|
import ca.uhn.fhir.context.support.IValidationSupport.LookupCodeResult;
|
||||||
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
|
@ -1,76 +1,17 @@
|
||||||
package org.hl7.fhir.common.hapi.validation;
|
package org.hl7.fhir.common.hapi.validation;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.createCodeValidationIssues;
|
|
||||||
|
|
||||||
public interface IRemoteTerminologyValidateCodeTest extends IValidateCodeTest {
|
public interface IRemoteTerminologyValidateCodeTest extends IValidateCodeTest {
|
||||||
default List<IValidationSupport.CodeValidationIssue> getCodeValidationIssues(IBaseOperationOutcome theOperationOutcome) {
|
default List<IValidationSupport.CodeValidationIssue> getCodeValidationIssues(IBaseOperationOutcome theOperationOutcome) {
|
||||||
// this method should be removed once support for issues is fully implemented across all validator types
|
// this method should be removed once support for issues is fully implemented across all validator types
|
||||||
Optional<Collection<IValidationSupport.CodeValidationIssue>> issues = RemoteTerminologyServiceValidationSupport.createCodeValidationIssues(theOperationOutcome, getService().getFhirContext().getVersion().getVersion());
|
Optional<Collection<IValidationSupport.CodeValidationIssue>> issues = RemoteTerminologyServiceValidationSupport.createCodeValidationIssues(theOperationOutcome, getService().getFhirContext().getVersion().getVersion());
|
||||||
return issues.map(theCodeValidationIssues -> theCodeValidationIssues.stream().toList()).orElseGet(List::of);
|
return issues.map(theCodeValidationIssues -> theCodeValidationIssues.stream().toList()).orElseGet(List::of);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
default void createCodeValidationIssues_withCodeSystemOutcomeForInvalidCode_returnsAsExpected() {
|
|
||||||
IBaseOperationOutcome outcome = getCodeSystemInvalidCodeOutcome();
|
|
||||||
FhirVersionEnum versionEnum = getService().getFhirContext().getVersion().getVersion();
|
|
||||||
Optional<Collection<IValidationSupport.CodeValidationIssue>> issuesOptional = createCodeValidationIssues(outcome, versionEnum);
|
|
||||||
assertThat(issuesOptional).isPresent();
|
|
||||||
assertThat(issuesOptional.get()).hasSize(1);
|
|
||||||
IValidationSupport.CodeValidationIssue issue = issuesOptional.get().iterator().next();
|
|
||||||
assertThat(issue.getType().getCode()).isEqualTo("code-invalid");
|
|
||||||
assertThat(issue.getSeverity().getCode()).isEqualTo("error");
|
|
||||||
assertThat(issue.getDetails().getCodings()).hasSize(1);
|
|
||||||
IValidationSupport.CodeValidationIssueCoding issueCoding = issue.getDetails().getCodings().get(0);
|
|
||||||
assertThat(issueCoding.getSystem()).isEqualTo("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type");
|
|
||||||
assertThat(issueCoding.getCode()).isEqualTo("invalid-code");
|
|
||||||
assertThat(issue.getDetails().getText()).isEqualTo("Unknown code 'CODE' in the CodeSystem 'http://code.system/url' version '1.0.0'");
|
|
||||||
assertThat(issue.getDiagnostics()).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
default void createCodeValidationIssues_withValueSetOutcomeForInvalidCode_returnsAsExpected() {
|
|
||||||
IBaseOperationOutcome outcome = getValueSetInvalidCodeOutcome();
|
|
||||||
FhirVersionEnum versionEnum = getService().getFhirContext().getVersion().getVersion();
|
|
||||||
Optional<Collection<IValidationSupport.CodeValidationIssue>> issuesOptional = createCodeValidationIssues(outcome, versionEnum);
|
|
||||||
assertThat(issuesOptional).isPresent();
|
|
||||||
assertThat(issuesOptional.get()).hasSize(2);
|
|
||||||
IValidationSupport.CodeValidationIssue issue = issuesOptional.get().iterator().next();
|
|
||||||
assertThat(issue.getType().getCode()).isEqualTo("code-invalid");
|
|
||||||
assertThat(issue.getSeverity().getCode()).isEqualTo("error");
|
|
||||||
assertThat(issue.getDetails().getCodings()).hasSize(1);
|
|
||||||
IValidationSupport.CodeValidationIssueCoding issueCoding = issue.getDetails().getCodings().get(0);
|
|
||||||
assertThat(issueCoding.getSystem()).isEqualTo("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type");
|
|
||||||
assertThat(issueCoding.getCode()).isEqualTo("not-in-vs");
|
|
||||||
assertThat(issue.getDetails().getText()).isEqualTo("The provided code 'http://code.system/url#CODE' was not found in the value set 'http://value.set/url%7C1.0.0'");
|
|
||||||
assertThat(issue.getDiagnostics()).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
default void createCodeValidationIssues_withValueSetOutcomeWithCustomDetailCode_returnsAsExpected() {
|
|
||||||
IBaseOperationOutcome outcome = getValueSetCustomDetailCodeOutcome();
|
|
||||||
FhirVersionEnum versionEnum = getService().getFhirContext().getVersion().getVersion();
|
|
||||||
Optional<Collection<IValidationSupport.CodeValidationIssue>> issuesOptional = createCodeValidationIssues(outcome, versionEnum);
|
|
||||||
assertThat(issuesOptional).isPresent();
|
|
||||||
assertThat(issuesOptional.get()).hasSize(1);
|
|
||||||
IValidationSupport.CodeValidationIssue issue = issuesOptional.get().iterator().next();
|
|
||||||
assertThat(issue.getType().getCode()).isEqualTo("processing");
|
|
||||||
assertThat(issue.getSeverity().getCode()).isEqualTo("information");
|
|
||||||
assertThat(issue.getDetails().getCodings()).hasSize(1);
|
|
||||||
IValidationSupport.CodeValidationIssueCoding issueCoding = issue.getDetails().getCodings().get(0);
|
|
||||||
assertThat(issueCoding.getSystem()).isEqualTo("http://example.com/custom-issue-type");
|
|
||||||
assertThat(issueCoding.getCode()).isEqualTo("valueset-is-draft");
|
|
||||||
assertThat(issue.getDetails().getText()).isNull();
|
|
||||||
assertThat(issue.getDiagnostics()).isEqualTo("The ValueSet status is marked as draft.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,6 @@ import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import ca.uhn.fhir.util.ClasspathUtil;
|
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -19,13 +16,12 @@ import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static ca.uhn.fhir.context.support.IValidationSupport.IssueSeverity.ERROR;
|
import static ca.uhn.fhir.context.support.IValidationSupport.IssueSeverity.ERROR;
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_VALIDATE_CODE;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.DISPLAY;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.DISPLAY;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.ERROR_MESSAGE;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.ERROR_MESSAGE;
|
import static org.hl7.fhir.common.hapi.validation.IValidationProviders.VALUE_SET_URL;
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.VALUE_SET_URL;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
@ -35,35 +31,21 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public interface IValidateCodeTest {
|
public interface IValidateCodeTest {
|
||||||
|
|
||||||
IValidationProviders.IMyValidationProvider getCodeSystemProvider();
|
IValidationProviders.IMyCodeSystemProvider getCodeSystemProvider();
|
||||||
IValidationProviders.IMyValidationProvider getValueSetProvider();
|
IValidationProviders.IMyValueSetProvider getValueSetProvider();
|
||||||
IValidationSupport getService();
|
IValidationSupport getService();
|
||||||
IBaseParameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource);
|
IBaseParameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource);
|
||||||
String getCodeSystemError();
|
String getCodeSystemError();
|
||||||
String getValueSetError();
|
String getValueSetError();
|
||||||
IBaseOperationOutcome getCodeSystemInvalidCodeOutcome();
|
IBaseOperationOutcome getCodeSystemInvalidCodeOutcome();
|
||||||
IBaseOperationOutcome getValueSetInvalidCodeOutcome();
|
IBaseOperationOutcome getValueSetInvalidCodeOutcome();
|
||||||
IBaseOperationOutcome getValueSetCustomDetailCodeOutcome();
|
|
||||||
|
|
||||||
default IBaseOperationOutcome getCodeSystemInvalidCodeOutcome(Class<? extends IBaseOperationOutcome> theResourceClass) {
|
|
||||||
return getOutcome(theResourceClass, "/terminology/OperationOutcome-CodeSystem-invalid-code.json");
|
|
||||||
}
|
|
||||||
default IBaseOperationOutcome getValueSetInvalidCodeOutcome(Class<? extends IBaseOperationOutcome> theResourceClass) {
|
|
||||||
return getOutcome(theResourceClass, "/terminology/OperationOutcome-ValueSet-invalid-code.json");
|
|
||||||
}
|
|
||||||
default IBaseOperationOutcome getValueSetCustomDetailCodeOutcome(Class<? extends IBaseOperationOutcome> theResourceClass) {
|
|
||||||
return getOutcome(theResourceClass, "/terminology/OperationOutcome-ValueSet-custom-issue-detail.json");
|
|
||||||
}
|
|
||||||
default IBaseOperationOutcome getOutcome(Class<? extends IBaseOperationOutcome> theResourceClass, String theFile) {
|
|
||||||
return ClasspathUtil.loadResource(getService().getFhirContext(), theResourceClass, theFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void createCodeSystemReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
default void createCodeSystemReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
getCodeSystemProvider().addTerminologyResponse(OPERATION_VALIDATE_CODE, CODE_SYSTEM, CODE, createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
getCodeSystemProvider().setReturnParams(createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void createValueSetReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
default void createValueSetReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
getValueSetProvider().addTerminologyResponse(OPERATION_VALIDATE_CODE, VALUE_SET_URL, CODE, createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
getValueSetProvider().setReturnParams(createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -109,8 +91,8 @@ public interface IValidateCodeTest {
|
||||||
String theValidationMessage,
|
String theValidationMessage,
|
||||||
String theCodeSystem,
|
String theCodeSystem,
|
||||||
String theValueSetUrl) {
|
String theValueSetUrl) {
|
||||||
getCodeSystemProvider().addException(OPERATION_VALIDATE_CODE, theCodeSystem, CODE, theException);
|
getCodeSystemProvider().setException(theException);
|
||||||
getValueSetProvider().addException(OPERATION_VALIDATE_CODE, theValueSetUrl, CODE, theException);
|
getValueSetProvider().setException(theException);
|
||||||
CodeValidationResult outcome = getService().validateCode(null, null, theCodeSystem, CODE, DISPLAY, theValueSetUrl);
|
CodeValidationResult outcome = getService().validateCode(null, null, theCodeSystem, CODE, DISPLAY, theValueSetUrl);
|
||||||
|
|
||||||
verifyErrorResultFromException(outcome, theValidationMessage, theServerMessage);
|
verifyErrorResultFromException(outcome, theValidationMessage, theServerMessage);
|
||||||
|
@ -123,7 +105,7 @@ public interface IValidateCodeTest {
|
||||||
for (String message : theMessages) {
|
for (String message : theMessages) {
|
||||||
assertTrue(outcome.getMessage().contains(message));
|
assertTrue(outcome.getMessage().contains(message));
|
||||||
}
|
}
|
||||||
assertFalse(outcome.getIssues().isEmpty());
|
assertFalse(outcome.getCodeValidationIssues().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -148,7 +130,11 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getValueSetProvider().getCode());
|
||||||
|
assertEquals(DISPLAY, getValueSetProvider().getDisplay());
|
||||||
|
assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -161,7 +147,9 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getCodeSystemProvider().getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -177,7 +165,10 @@ public interface IValidateCodeTest {
|
||||||
assertNull(outcome.getDisplay());
|
assertNull(outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getCodeSystemProvider().getCode());
|
||||||
|
assertEquals(CODE_SYSTEM, getCodeSystemProvider().getSystem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -193,11 +184,15 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getCodeSystemProvider().getCode());
|
||||||
|
assertEquals(DISPLAY, getCodeSystemProvider().getDisplay());
|
||||||
|
assertEquals(CODE_SYSTEM, getCodeSystemProvider().getSystem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
default void validateCode_withCodeSystemErrorWithDiagnosticsWithIssues_returnsCorrectly() {
|
default void validateCode_withCodeSystemError_returnsCorrectly() {
|
||||||
IBaseOperationOutcome invalidCodeOutcome = getCodeSystemInvalidCodeOutcome();
|
IBaseOperationOutcome invalidCodeOutcome = getCodeSystemInvalidCodeOutcome();
|
||||||
createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, invalidCodeOutcome);
|
createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, invalidCodeOutcome);
|
||||||
|
|
||||||
|
@ -209,12 +204,12 @@ public interface IValidateCodeTest {
|
||||||
// assertEquals(CODE, outcome.getCode());
|
// assertEquals(CODE, outcome.getCode());
|
||||||
assertEquals(ERROR, outcome.getSeverity());
|
assertEquals(ERROR, outcome.getSeverity());
|
||||||
assertEquals(getCodeSystemError(), outcome.getMessage());
|
assertEquals(getCodeSystemError(), outcome.getMessage());
|
||||||
assertFalse(outcome.getIssues().isEmpty());
|
assertFalse(outcome.getCodeValidationIssues().isEmpty());
|
||||||
verifyIssues(invalidCodeOutcome, outcome);
|
verifyIssues(invalidCodeOutcome, outcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
default void validateCode_withCodeSystemErrorWithDiagnosticsWithoutIssues_returnsCorrectly() {
|
default void validateCode_withCodeSystemErrorAndIssues_returnsCorrectly() {
|
||||||
createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, null);
|
createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, null);
|
||||||
|
|
||||||
CodeValidationResult outcome = getService()
|
CodeValidationResult outcome = getService()
|
||||||
|
@ -228,32 +223,10 @@ public interface IValidateCodeTest {
|
||||||
assertNull(outcome.getDisplay());
|
assertNull(outcome.getDisplay());
|
||||||
assertEquals(ERROR, outcome.getSeverity());
|
assertEquals(ERROR, outcome.getSeverity());
|
||||||
assertEquals(expectedError, outcome.getMessage());
|
assertEquals(expectedError, outcome.getMessage());
|
||||||
assertFalse(outcome.getIssues().isEmpty());
|
assertFalse(outcome.getCodeValidationIssues().isEmpty());
|
||||||
assertEquals(1, outcome.getIssues().size());
|
assertEquals(1, outcome.getCodeValidationIssues().size());
|
||||||
assertEquals(expectedError, outcome.getIssues().get(0).getDiagnostics());
|
assertEquals(expectedError, outcome.getCodeValidationIssues().get(0).getMessage());
|
||||||
assertEquals(ERROR, outcome.getIssues().get(0).getSeverity());
|
assertEquals(ERROR, outcome.getCodeValidationIssues().get(0).getSeverity());
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
default void validateCode_withCodeSystemErrorWithoutDiagnosticsWithIssues_returnsCorrectly() {
|
|
||||||
IBaseOperationOutcome invalidCodeOutcome = getCodeSystemInvalidCodeOutcome();
|
|
||||||
createCodeSystemReturnParameters(false, null, null, invalidCodeOutcome);
|
|
||||||
|
|
||||||
CodeValidationResult outcome = getService()
|
|
||||||
.validateCode(null, null, CODE_SYSTEM, CODE, null, null);
|
|
||||||
|
|
||||||
String expectedError = getCodeSystemError();
|
|
||||||
assertNotNull(outcome);
|
|
||||||
assertEquals(CODE_SYSTEM, outcome.getCodeSystemName());
|
|
||||||
assertEquals(CODE_SYSTEM_VERSION, outcome.getCodeSystemVersion());
|
|
||||||
// assertEquals(CODE, outcome.getCode());
|
|
||||||
assertNull(outcome.getDisplay());
|
|
||||||
assertEquals(ERROR, outcome.getSeverity());
|
|
||||||
assertNull(outcome.getMessage());
|
|
||||||
assertFalse(outcome.getIssues().isEmpty());
|
|
||||||
assertEquals(1, outcome.getIssues().size());
|
|
||||||
assertNull(outcome.getIssues().get(0).getDiagnostics());
|
|
||||||
assertEquals(ERROR, outcome.getIssues().get(0).getSeverity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -269,7 +242,10 @@ public interface IValidateCodeTest {
|
||||||
assertNull(outcome.getDisplay());
|
assertNull(outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getValueSetProvider().getCode());
|
||||||
|
assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -285,7 +261,11 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
assertTrue(outcome.getIssues().isEmpty());
|
assertTrue(outcome.getCodeValidationIssues().isEmpty());
|
||||||
|
|
||||||
|
assertEquals(CODE, getValueSetProvider().getCode());
|
||||||
|
assertEquals(DISPLAY, getValueSetProvider().getDisplay());
|
||||||
|
assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -303,9 +283,13 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertEquals(ERROR, outcome.getSeverity());
|
assertEquals(ERROR, outcome.getSeverity());
|
||||||
assertEquals(expectedError, outcome.getMessage());
|
assertEquals(expectedError, outcome.getMessage());
|
||||||
assertEquals(1, outcome.getIssues().size());
|
assertEquals(1, outcome.getCodeValidationIssues().size());
|
||||||
assertEquals(expectedError, outcome.getIssues().get(0).getDiagnostics());
|
assertEquals(expectedError, outcome.getCodeValidationIssues().get(0).getMessage());
|
||||||
assertEquals(ERROR, outcome.getIssues().get(0).getSeverity());
|
assertEquals(ERROR, outcome.getCodeValidationIssues().get(0).getSeverity());
|
||||||
|
|
||||||
|
assertEquals(CODE, getValueSetProvider().getCode());
|
||||||
|
assertEquals(DISPLAY, getValueSetProvider().getDisplay());
|
||||||
|
assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -322,28 +306,24 @@ public interface IValidateCodeTest {
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(DISPLAY, outcome.getDisplay());
|
||||||
assertEquals(ERROR, outcome.getSeverity());
|
assertEquals(ERROR, outcome.getSeverity());
|
||||||
assertEquals(getValueSetError(), outcome.getMessage());
|
assertEquals(getValueSetError(), outcome.getMessage());
|
||||||
assertFalse(outcome.getIssues().isEmpty());
|
assertFalse(outcome.getCodeValidationIssues().isEmpty());
|
||||||
verifyIssues(invalidCodeOutcome, outcome);
|
verifyIssues(invalidCodeOutcome, outcome);
|
||||||
|
|
||||||
|
assertEquals(CODE, getValueSetProvider().getCode());
|
||||||
|
assertEquals(DISPLAY, getValueSetProvider().getDisplay());
|
||||||
|
assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
default void verifyIssues(IBaseOperationOutcome theOperationOutcome, CodeValidationResult theResult) {
|
default void verifyIssues(IBaseOperationOutcome theOperationOutcome, CodeValidationResult theResult) {
|
||||||
List<IValidationSupport.CodeValidationIssue> issues = getCodeValidationIssues(theOperationOutcome);
|
List<IValidationSupport.CodeValidationIssue> issues = getCodeValidationIssues(theOperationOutcome);
|
||||||
assertEquals(issues.size(), theResult.getIssues().size());
|
assertEquals(issues.size(), theResult.getCodeValidationIssues().size());
|
||||||
for (int i = 0; i < issues.size(); i++) {
|
for (int i = 0; i < issues.size(); i++) {
|
||||||
IValidationSupport.CodeValidationIssue expectedIssue = issues.get(i);
|
IValidationSupport.CodeValidationIssue expectedIssue = issues.get(i);
|
||||||
IValidationSupport.CodeValidationIssue actualIssue = theResult.getIssues().get(i);
|
IValidationSupport.CodeValidationIssue actualIssue = theResult.getCodeValidationIssues().get(i);
|
||||||
assertEquals(expectedIssue.getType().getCode(), actualIssue.getType().getCode());
|
assertEquals(expectedIssue.getCode(), actualIssue.getCode());
|
||||||
assertEquals(expectedIssue.getSeverity(), actualIssue.getSeverity());
|
assertEquals(expectedIssue.getSeverity(), actualIssue.getSeverity());
|
||||||
assertEquals(expectedIssue.getDetails().getText(), actualIssue.getDetails().getText());
|
assertEquals(expectedIssue.getCoding(), actualIssue.getCoding());
|
||||||
assertEquals(expectedIssue.getDetails().getCodings().size(), actualIssue.getDetails().getCodings().size());
|
assertEquals(expectedIssue.getMessage(), actualIssue.getMessage());
|
||||||
for (int index = 0; index < expectedIssue.getDetails().getCodings().size(); index++) {
|
|
||||||
IValidationSupport.CodeValidationIssueCoding expectedCoding = expectedIssue.getDetails().getCodings().get(index);
|
|
||||||
IValidationSupport.CodeValidationIssueCoding actualCoding = actualIssue.getDetails().getCodings().get(index);
|
|
||||||
assertEquals(expectedCoding.getSystem(), actualCoding.getSystem());
|
|
||||||
assertEquals(expectedCoding.getCode(), actualCoding.getCode());
|
|
||||||
}
|
|
||||||
assertEquals(expectedIssue.getDetails().getText(), actualIssue.getDetails().getText());
|
|
||||||
assertEquals(expectedIssue.getDiagnostics(), actualIssue.getDiagnostics());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.hl7.fhir.common.hapi.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
|
||||||
|
public interface IValidationProviders {
|
||||||
|
String CODE_SYSTEM = "http://code.system/url";
|
||||||
|
String CODE_SYSTEM_VERSION = "1.0.0";
|
||||||
|
String CODE_SYSTEM_NAME = "Test Code System";
|
||||||
|
String CODE = "CODE";
|
||||||
|
String VALUE_SET_URL = "http://value.set/url";
|
||||||
|
String DISPLAY = "Explanation for code TestCode.";
|
||||||
|
String LANGUAGE = "en";
|
||||||
|
String ERROR_MESSAGE = "This is an error message";
|
||||||
|
|
||||||
|
interface IMyCodeSystemProvider extends IResourceProvider {
|
||||||
|
String getCode();
|
||||||
|
String getSystem();
|
||||||
|
String getDisplay();
|
||||||
|
void setException(Exception theException);
|
||||||
|
void setReturnParams(IBaseParameters theParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMyLookupCodeProvider extends IResourceProvider {
|
||||||
|
String getCode();
|
||||||
|
String getSystem();
|
||||||
|
void setLookupCodeResult(IValidationSupport.LookupCodeResult theLookupCodeResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMyValueSetProvider extends IResourceProvider {
|
||||||
|
String getCode();
|
||||||
|
String getSystem();
|
||||||
|
String getDisplay();
|
||||||
|
String getValueSet();
|
||||||
|
void setException(Exception theException);
|
||||||
|
void setReturnParams(IBaseParameters theParameters);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks;
|
import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks;
|
||||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||||
|
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||||
|
@ -15,18 +16,17 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.quality.Strictness;
|
import org.mockito.quality.Strictness;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.mockito.Mockito.withSettings;
|
import static org.mockito.Mockito.withSettings;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestWithInlineMocks {
|
public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestWithInlineMocks {
|
||||||
|
|
||||||
final byte[] EXPECTED_BINARY_CONTENT_1 = "dummyBinaryContent1".getBytes();
|
final byte[] EXPECTED_BINARY_CONTENT_1 = "dummyBinaryContent1".getBytes();
|
||||||
|
@ -80,7 +80,7 @@ public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestW
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCode_codeInValueSet_resolvesCodeSystemFromValueSet() {
|
public void validateCode_normally_resolvesCodeSystemFromValueSet() {
|
||||||
// setup
|
// setup
|
||||||
IValidationSupport validationSupport = mockValidationSupport();
|
IValidationSupport validationSupport = mockValidationSupport();
|
||||||
ValidationSupportContext mockContext = mockValidationSupportContext(validationSupport);
|
ValidationSupportContext mockContext = mockValidationSupportContext(validationSupport);
|
||||||
|
@ -90,7 +90,8 @@ public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestW
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system").addConcept().setCode("code0");
|
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system").addConcept().setCode("code0");
|
||||||
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system2").addConcept().setCode("code2");
|
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system2").addConcept().setCode("code2");
|
||||||
when(validationSupport.validateCodeInValueSet(any(), any(), any(), any(), any(), any())).thenReturn(mock(IValidationSupport.CodeValidationResult.class));
|
when(validationSupport.fetchResource(eq(ValueSet.class), eq("http://somevalueset"))).thenReturn(valueSet);
|
||||||
|
when(validationSupport.validateCodeInValueSet(any(), any(), any(), any(), any(), any())).thenReturn(new IValidationSupport.CodeValidationResult());
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
wrapper.validateCode(new ValidationOptions(), "code0", valueSet);
|
wrapper.validateCode(new ValidationOptions(), "code0", valueSet);
|
||||||
|
@ -100,26 +101,6 @@ public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestW
|
||||||
verify(validationSupport, times(1)).validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), any());
|
verify(validationSupport, times(1)).validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validateCode_codeNotInValueSet_doesNotResolveSystem() {
|
|
||||||
// setup
|
|
||||||
IValidationSupport validationSupport = mockValidationSupport();
|
|
||||||
ValidationSupportContext mockContext = mockValidationSupportContext(validationSupport);
|
|
||||||
VersionCanonicalizer versionCanonicalizer = new VersionCanonicalizer(FhirContext.forR5Cached());
|
|
||||||
VersionSpecificWorkerContextWrapper wrapper = new VersionSpecificWorkerContextWrapper(mockContext, versionCanonicalizer);
|
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
|
||||||
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system").addConcept().setCode("code0");
|
|
||||||
valueSet.getCompose().addInclude().setSystem("http://codesystems.com/system2").addConcept().setCode("code2");
|
|
||||||
|
|
||||||
// execute
|
|
||||||
wrapper.validateCode(new ValidationOptions(), "code1", valueSet);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
verify(validationSupport, times(1)).validateCodeInValueSet(any(), any(), eq(null), eq("code1"), any(), any());
|
|
||||||
verify(validationSupport, never()).validateCode(any(), any(), any(), any(), any(), any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isPrimitive_primitive() {
|
public void isPrimitive_primitive() {
|
||||||
// setup
|
// setup
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks;
|
import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||||
|
@ -27,7 +28,10 @@ import org.hl7.fhir.dstu2.model.Observation.ObservationStatus;
|
||||||
import org.hl7.fhir.dstu2.model.QuestionnaireResponse;
|
import org.hl7.fhir.dstu2.model.QuestionnaireResponse;
|
||||||
import org.hl7.fhir.dstu2.model.QuestionnaireResponse.QuestionnaireResponseStatus;
|
import org.hl7.fhir.dstu2.model.QuestionnaireResponse.QuestionnaireResponseStatus;
|
||||||
import org.hl7.fhir.dstu2.model.StringType;
|
import org.hl7.fhir.dstu2.model.StringType;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -37,7 +41,9 @@ import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -94,7 +100,7 @@ public class FhirInstanceValidatorDstu2Test extends BaseValidationTestWithInline
|
||||||
if (myValidConcepts.contains(system + "___" + code)) {
|
if (myValidConcepts.contains(system + "___" + code)) {
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
||||||
} else if (myValidSystems.contains(system)) {
|
} else if (myValidSystems.contains(system)) {
|
||||||
return new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage("Unknown code");
|
return new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage("Unknown code");
|
||||||
} else {
|
} else {
|
||||||
retVal = null;
|
retVal = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
@ -228,10 +229,10 @@ public class FhirInstanceValidatorDstu3Test extends BaseValidationTestWithInline
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
||||||
} else if (myValidSystems.contains(system)) {
|
} else if (myValidSystems.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message).setIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
retVal = new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message).setCodeValidationIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
||||||
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message);
|
retVal = new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message);
|
||||||
} else if (myCodeSystems.containsKey(system)) {
|
} else if (myCodeSystems.containsKey(system)) {
|
||||||
CodeSystem cs = myCodeSystems.get(system);
|
CodeSystem cs = myCodeSystems.get(system);
|
||||||
Optional<ConceptDefinitionComponent> found = cs.getConcept().stream().filter(t -> t.getCode().equals(code)).findFirst();
|
Optional<ConceptDefinitionComponent> found = cs.getConcept().stream().filter(t -> t.getCode().equals(code)).findFirst();
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
package org.hl7.fhir.dstu3.hapi.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
|
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IValidateCodeProvidersDstu3 {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
class MyCodeSystemProviderDstu3 implements IValidationProviders.IMyCodeSystemProvider {
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private CodeType myCode;
|
||||||
|
private StringType myDisplay;
|
||||||
|
private Exception myException;
|
||||||
|
private Parameters myReturnParams;
|
||||||
|
|
||||||
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
|
@OperationParam(name = "result", type = org.hl7.fhir.dstu3.model.BooleanType.class, min = 1),
|
||||||
|
@OperationParam(name = "message", type = org.hl7.fhir.dstu3.model.StringType.class),
|
||||||
|
@OperationParam(name = "display", type = org.hl7.fhir.dstu3.model.StringType.class)
|
||||||
|
})
|
||||||
|
public org.hl7.fhir.dstu3.model.Parameters validateCode(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
@IdParam(optional = true) org.hl7.fhir.dstu3.model.IdType theId,
|
||||||
|
@OperationParam(name = "url", min = 0, max = 1) org.hl7.fhir.dstu3.model.UriType theCodeSystemUrl,
|
||||||
|
@OperationParam(name = "code", min = 0, max = 1) org.hl7.fhir.dstu3.model.CodeType theCode,
|
||||||
|
@OperationParam(name = "display", min = 0, max = 1) org.hl7.fhir.dstu3.model.StringType theDisplay
|
||||||
|
) throws Exception {
|
||||||
|
mySystemUrl = theCodeSystemUrl;
|
||||||
|
myCode = theCode;
|
||||||
|
myDisplay = theDisplay;
|
||||||
|
if (myException != null) {
|
||||||
|
throw myException;
|
||||||
|
}
|
||||||
|
return myReturnParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters= {
|
||||||
|
@OperationParam(name = "name", type = org.hl7.fhir.dstu3.model.StringType.class, min = 1),
|
||||||
|
@OperationParam(name = "version", type = org.hl7.fhir.dstu3.model.StringType.class),
|
||||||
|
@OperationParam(name = "display", type = org.hl7.fhir.dstu3.model.StringType.class, min = 1),
|
||||||
|
@OperationParam(name = "abstract", type = org.hl7.fhir.dstu3.model.BooleanType.class, min = 1),
|
||||||
|
@OperationParam(name = "property", type = org.hl7.fhir.dstu3.model.StringType.class, min = 0, max = OperationParam.MAX_UNLIMITED)
|
||||||
|
})
|
||||||
|
public IBaseParameters lookup(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
@OperationParam(name = "code", max = 1) org.hl7.fhir.dstu3.model.CodeType theCode,
|
||||||
|
@OperationParam(name = "system",max = 1) org.hl7.fhir.dstu3.model.UriType theSystem,
|
||||||
|
@OperationParam(name = "coding", max = 1) Coding theCoding,
|
||||||
|
@OperationParam(name = "version", max = 1) org.hl7.fhir.dstu3.model.StringType theVersion,
|
||||||
|
@OperationParam(name = "displayLanguage", max = 1) org.hl7.fhir.dstu3.model.CodeType theDisplayLanguage,
|
||||||
|
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<org.hl7.fhir.dstu3.model.CodeType> thePropertyNames,
|
||||||
|
RequestDetails theRequestDetails
|
||||||
|
) {
|
||||||
|
myCode = theCode;
|
||||||
|
return myReturnParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return CodeSystem.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(Exception theException) {
|
||||||
|
myException = theException;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setReturnParams(IBaseParameters theParameters) {
|
||||||
|
myReturnParams = (Parameters) theParameters;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
public String getDisplay() {
|
||||||
|
return myDisplay != null ? myDisplay.getValue() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
class MyValueSetProviderDstu3 implements IValidationProviders.IMyValueSetProvider {
|
||||||
|
private Exception myException;
|
||||||
|
private Parameters myReturnParams;
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private UriType myValueSetUrl;
|
||||||
|
private CodeType myCode;
|
||||||
|
private StringType myDisplay;
|
||||||
|
|
||||||
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
|
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
||||||
|
@OperationParam(name = "message", type = org.hl7.fhir.dstu3.model.StringType.class),
|
||||||
|
@OperationParam(name = "display", type = org.hl7.fhir.dstu3.model.StringType.class)
|
||||||
|
})
|
||||||
|
public Parameters validateCode(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
@IdParam(optional = true) IdType theId,
|
||||||
|
@OperationParam(name = "url", min = 0, max = 1) org.hl7.fhir.dstu3.model.UriType theValueSetUrl,
|
||||||
|
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
||||||
|
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
|
||||||
|
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
|
||||||
|
@OperationParam(name = "valueSet") org.hl7.fhir.dstu3.model.ValueSet theValueSet
|
||||||
|
) throws Exception {
|
||||||
|
mySystemUrl = theSystem;
|
||||||
|
myValueSetUrl = theValueSetUrl;
|
||||||
|
myCode = theCode;
|
||||||
|
myDisplay = theDisplay;
|
||||||
|
if (myException != null) {
|
||||||
|
throw myException;
|
||||||
|
}
|
||||||
|
return myReturnParams;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return ValueSet.class;
|
||||||
|
}
|
||||||
|
public void setException(Exception theException) {
|
||||||
|
myException = theException;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setReturnParams(IBaseParameters theParameters) {
|
||||||
|
myReturnParams = (Parameters) theParameters;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getValueSet() {
|
||||||
|
return myValueSetUrl != null ? myValueSetUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
public String getDisplay() {
|
||||||
|
return myDisplay != null ? myDisplay.getValue() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ import org.hl7.fhir.dstu3.model.Type;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -55,8 +56,6 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ca.uhn.fhir.context.support.IValidationSupport.IssueSeverity.ERROR;
|
|
||||||
import static ca.uhn.fhir.context.support.IValidationSupport.IssueSeverity.WARNING;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.BOOLEAN;
|
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.BOOLEAN;
|
||||||
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.CHOICE;
|
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.CHOICE;
|
||||||
|
@ -225,7 +224,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
|
||||||
when(myValSupport.validateCodeInValueSet(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(ValueSet.class)))
|
when(myValSupport.validateCodeInValueSet(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(ValueSet.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0"));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0"));
|
||||||
when(myValSupport.validateCodeInValueSet(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(ValueSet.class)))
|
when(myValSupport.validateCodeInValueSet(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(ValueSet.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverity(ERROR).setMessage("Unknown code"));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage("Unknown code"));
|
||||||
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
@ -247,7 +246,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
|
||||||
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(String.class)))
|
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(String.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setCode(CODE_ICC_SCHOOLTYPE_PT));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setCode(CODE_ICC_SCHOOLTYPE_PT));
|
||||||
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(String.class)))
|
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(String.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverity(WARNING).setMessage("Unknown code: http://codesystems.com/system / code1"));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverityCode("warning").setMessage("Unknown code: http://codesystems.com/system / code1"));
|
||||||
|
|
||||||
|
|
||||||
QuestionnaireResponse qa;
|
QuestionnaireResponse qa;
|
||||||
|
@ -1035,7 +1034,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
|
||||||
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(String.class)))
|
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(String.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0"));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0"));
|
||||||
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(String.class)))
|
when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code1"), any(), nullable(String.class)))
|
||||||
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverity(ERROR).setMessage("Unknown code"));
|
.thenReturn(new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage("Unknown code"));
|
||||||
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
|
|
@ -12,9 +12,9 @@ import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyLookupCodeTest;
|
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyLookupCodeTest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
|
@ -164,6 +164,8 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
static class MyLookupCodeProviderDstu3 implements IValidationProviders.IMyLookupCodeProvider {
|
static class MyLookupCodeProviderDstu3 implements IValidationProviders.IMyLookupCodeProvider {
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private CodeType myCode;
|
||||||
private LookupCodeResult myLookupCodeResult;
|
private LookupCodeResult myLookupCodeResult;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,6 +190,8 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL
|
||||||
@OperationParam(name= " property", max = OperationParam.MAX_UNLIMITED) List<StringType> thePropertyNames,
|
@OperationParam(name= " property", max = OperationParam.MAX_UNLIMITED) List<StringType> thePropertyNames,
|
||||||
RequestDetails theRequestDetails
|
RequestDetails theRequestDetails
|
||||||
) {
|
) {
|
||||||
|
myCode = theCode;
|
||||||
|
mySystemUrl = theSystem;
|
||||||
if (theSystem == null) {
|
if (theSystem == null) {
|
||||||
throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode));
|
throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode));
|
||||||
}
|
}
|
||||||
|
@ -201,5 +205,15 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
return CodeSystem.class;
|
return CodeSystem.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,13 @@ import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersDstu3;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -16,15 +19,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_LOOKUP;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test {
|
public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test {
|
||||||
private static final FhirContext ourCtx = FhirContext.forDstu3Cached();
|
private static final FhirContext ourCtx = FhirContext.forDstu3Cached();
|
||||||
private IValidationProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider;
|
private IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider;
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test {
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
||||||
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
||||||
myCodeSystemProvider = new IValidationProvidersDstu3.MyCodeSystemProviderDstu3();
|
myCodeSystemProvider = new IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3();
|
||||||
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider);
|
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +47,13 @@ public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test {
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
void lookupCode_withParametersOutput_convertsCorrectly() {
|
void lookupCode_withParametersOutput_convertsCorrectly() {
|
||||||
String outputFile ="/terminology/CodeSystem-lookup-output-with-subproperties.json";
|
String paramsAsString = ClasspathUtil.loadResource("/terminology/CodeSystem-lookup-output-with-subproperties.json");
|
||||||
IBaseParameters resultParameters = myCodeSystemProvider.addTerminologyResponse(OPERATION_LOOKUP, CODE_SYSTEM, CODE, ourCtx, outputFile);
|
IBaseResource baseResource = ourCtx.newJsonParser().parseResource(paramsAsString);
|
||||||
|
assertTrue(baseResource instanceof Parameters);
|
||||||
|
Parameters resultParameters = (Parameters) baseResource;
|
||||||
|
myCodeSystemProvider.setReturnParams(resultParameters);
|
||||||
|
|
||||||
LookupCodeRequest request = new LookupCodeRequest(CODE_SYSTEM, CODE, null, List.of("interfaces"));
|
LookupCodeRequest request = new LookupCodeRequest(IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, null, List.of("interfaces"));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request);
|
IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request);
|
||||||
|
|
|
@ -4,18 +4,16 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersDstu3;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyValidateCodeTest;
|
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyValidateCodeTest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.Resource;
|
import org.hl7.fhir.dstu3.model.Resource;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -24,11 +22,6 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.ERROR_MESSAGE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.VALUE_SET_URL;
|
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM;
|
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM;
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET;
|
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET;
|
||||||
|
|
||||||
|
@ -45,8 +38,8 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog
|
||||||
private static final FhirContext ourCtx = FhirContext.forDstu3Cached();
|
private static final FhirContext ourCtx = FhirContext.forDstu3Cached();
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
private IValidationProviders.MyValidationProvider<CodeSystem> myCodeSystemProvider;
|
private IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider;
|
||||||
private IValidationProviders.MyValidationProvider<ValueSet> myValueSetProvider;
|
private IValidateCodeProvidersDstu3.MyValueSetProviderDstu3 myValueSetProvider;
|
||||||
private RemoteTerminologyServiceValidationSupport mySvc;
|
private RemoteTerminologyServiceValidationSupport mySvc;
|
||||||
private String myCodeSystemError, myValueSetError;
|
private String myCodeSystemError, myValueSetError;
|
||||||
|
|
||||||
|
@ -55,14 +48,14 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
myCodeSystemError = ourCtx.getLocalizer().getMessage(
|
myCodeSystemError = ourCtx.getLocalizer().getMessage(
|
||||||
RemoteTerminologyServiceValidationSupport.class,
|
RemoteTerminologyServiceValidationSupport.class,
|
||||||
ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM, CODE_SYSTEM, CODE, baseUrl, ERROR_MESSAGE);
|
ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM, IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, baseUrl, IValidationProviders.ERROR_MESSAGE);
|
||||||
myValueSetError = ourCtx.getLocalizer().getMessage(
|
myValueSetError = ourCtx.getLocalizer().getMessage(
|
||||||
RemoteTerminologyServiceValidationSupport.class,
|
RemoteTerminologyServiceValidationSupport.class,
|
||||||
ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET, CODE_SYSTEM, CODE, VALUE_SET_URL, baseUrl, ERROR_MESSAGE);
|
ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET, IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, IValidationProviders.VALUE_SET_URL, baseUrl, IValidationProviders.ERROR_MESSAGE);
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
||||||
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
||||||
myCodeSystemProvider = new IValidationProvidersDstu3.MyCodeSystemProviderDstu3();
|
myCodeSystemProvider = new IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3();
|
||||||
myValueSetProvider = new IValidationProvidersDstu3.MyValueSetProviderDstu3();
|
myValueSetProvider = new IValidateCodeProvidersDstu3.MyValueSetProviderDstu3();
|
||||||
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider);
|
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,40 +82,45 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IValidationProviders.IMyValidationProvider getCodeSystemProvider() {
|
public IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 getCodeSystemProvider() {
|
||||||
return myCodeSystemProvider;
|
return myCodeSystemProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IValidationProviders.IMyValidationProvider getValueSetProvider() {
|
public IValidateCodeProvidersDstu3.MyValueSetProviderDstu3 getValueSetProvider() {
|
||||||
return myValueSetProvider;
|
return myValueSetProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() {
|
public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() {
|
||||||
return getCodeSystemInvalidCodeOutcome(OperationOutcome.class);
|
return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-CodeSystem-invalid-code.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseOperationOutcome getValueSetInvalidCodeOutcome() {
|
public IBaseOperationOutcome getValueSetInvalidCodeOutcome() {
|
||||||
return getValueSetInvalidCodeOutcome(OperationOutcome.class);
|
return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-ValueSet-invalid-code.json");
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBaseOperationOutcome getValueSetCustomDetailCodeOutcome() {
|
|
||||||
return getValueSetCustomDetailCodeOutcome(OperationOutcome.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
Parameters parameters = new Parameters();
|
Parameters parameters = new Parameters();
|
||||||
parameters.addParameter().setName("result").setValue(new BooleanType(theResult));
|
parameters.addParameter().setName("result").setValue(new BooleanType(theResult));
|
||||||
parameters.addParameter().setName("code").setValue(new StringType(CODE));
|
parameters.addParameter().setName("code").setValue(new StringType(IValidationProviders.CODE));
|
||||||
parameters.addParameter().setName("system").setValue(new UriType(CODE_SYSTEM));
|
parameters.addParameter().setName("system").setValue(new UriType(IValidationProviders.CODE_SYSTEM));
|
||||||
parameters.addParameter().setName("version").setValue(new StringType(CODE_SYSTEM_VERSION));
|
parameters.addParameter().setName("version").setValue(new StringType(IValidationProviders.CODE_SYSTEM_VERSION));
|
||||||
parameters.addParameter().setName("display").setValue(new StringType(theDisplay));
|
parameters.addParameter().setName("display").setValue(new StringType(theDisplay));
|
||||||
parameters.addParameter().setName("message").setValue(new StringType(theMessage));
|
parameters.addParameter().setName("message").setValue(new StringType(theMessage));
|
||||||
parameters.addParameter().setName("issues").setResource((Resource) theIssuesResource);
|
parameters.addParameter().setName("issues").setResource((Resource) theIssuesResource);
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createCodeSystemReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
|
myCodeSystemProvider.setReturnParams(createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createValueSetReturnParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
|
myValueSetProvider.setReturnParams(createParameters(theResult, theDisplay, theMessage, theIssuesResource));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,10 +307,10 @@ public class FhirInstanceValidatorR4Test extends BaseValidationTestWithInlineMoc
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
||||||
} else if (myValidSystems.contains(system)) {
|
} else if (myValidSystems.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message).setIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
retVal = new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message).setCodeValidationIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
||||||
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message);
|
retVal = new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message);
|
||||||
} else {
|
} else {
|
||||||
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package ca.uhn.fhir.test.utilities.validation;
|
package org.hl7.fhir.r4.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.BooleanType;
|
import org.hl7.fhir.r4.model.BooleanType;
|
||||||
|
@ -19,29 +21,38 @@ import org.hl7.fhir.r4.model.ValueSet;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IValidationProvidersR4 {
|
public interface IValidateCodeProvidersR4 {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
class MyCodeSystemProviderR4 extends IValidationProviders.MyValidationProvider<CodeSystem> {
|
class MyCodeSystemProviderR4 implements IValidationProviders.IMyCodeSystemProvider {
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private CodeType myCode;
|
||||||
|
private StringType myDisplay;
|
||||||
|
private Exception myException;
|
||||||
|
private Parameters myReturnParams;
|
||||||
|
|
||||||
@Operation(name = "$validate-code", idempotent = true, returnParameters = {
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
||||||
@OperationParam(name = "message", type = StringType.class),
|
@OperationParam(name = "message", type = StringType.class),
|
||||||
@OperationParam(name = "display", type = StringType.class)
|
@OperationParam(name = "display", type = StringType.class)
|
||||||
})
|
})
|
||||||
public IBaseParameters validateCode(
|
public Parameters validateCode(
|
||||||
HttpServletRequest theServletRequest,
|
HttpServletRequest theServletRequest,
|
||||||
@IdParam(optional = true) IdType theId,
|
@IdParam(optional = true) IdType theId,
|
||||||
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
|
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
|
||||||
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
||||||
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay
|
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
String url = theCodeSystemUrl != null ? theCodeSystemUrl.getValue() : null;
|
mySystemUrl = theCodeSystemUrl;
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
myCode = theCode;
|
||||||
return getTerminologyResponse("$validate-code", url, code);
|
myDisplay = theDisplay;
|
||||||
|
if (myException != null) {
|
||||||
|
throw myException;
|
||||||
|
}
|
||||||
|
return myReturnParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = "$lookup", idempotent = true, returnParameters= {
|
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters= {
|
||||||
@OperationParam(name = "name", type = StringType.class, min = 1),
|
@OperationParam(name = "name", type = StringType.class, min = 1),
|
||||||
@OperationParam(name = "version", type = StringType.class),
|
@OperationParam(name = "version", type = StringType.class),
|
||||||
@OperationParam(name = "display", type = StringType.class, min = 1),
|
@OperationParam(name = "display", type = StringType.class, min = 1),
|
||||||
|
@ -58,39 +69,54 @@ public interface IValidationProvidersR4 {
|
||||||
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<CodeType> thePropertyNames,
|
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<CodeType> thePropertyNames,
|
||||||
RequestDetails theRequestDetails
|
RequestDetails theRequestDetails
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
String url = theSystem != null ? theSystem.getValue() : null;
|
mySystemUrl = theSystem;
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
myCode = theCode;
|
||||||
return getTerminologyResponse("$lookup", url, code);
|
if (myException != null) {
|
||||||
|
throw myException;
|
||||||
|
}
|
||||||
|
return myReturnParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
return CodeSystem.class;
|
return CodeSystem.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setException(Exception theException) {
|
||||||
Class<Parameters> getParameterType() {
|
myException = theException;
|
||||||
return Parameters.class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CodeSystem addTerminologyResource(String theUrl) {
|
public void setReturnParams(IBaseParameters theParameters) {
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
myReturnParams = (Parameters) theParameters;
|
||||||
codeSystem.setId(theUrl.substring(0, theUrl.lastIndexOf("/")));
|
}
|
||||||
codeSystem.setUrl(theUrl);
|
@Override
|
||||||
addTerminologyResource(theUrl, codeSystem);
|
public String getCode() {
|
||||||
return codeSystem;
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
public String getDisplay() {
|
||||||
|
return myDisplay != null ? myDisplay.getValue() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
class MyValueSetProviderR4 extends IValidationProviders.MyValidationProvider<ValueSet> {
|
class MyValueSetProviderR4 implements IValidationProviders.IMyValueSetProvider {
|
||||||
|
private Exception myException;
|
||||||
|
private Parameters myReturnParams;
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private UriType myValueSetUrl;
|
||||||
|
private CodeType myCode;
|
||||||
|
private StringType myDisplay;
|
||||||
|
|
||||||
@Operation(name = "$validate-code", idempotent = true, returnParameters = {
|
@Operation(name = "validate-code", idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
@OperationParam(name = "result", type = BooleanType.class, min = 1),
|
||||||
@OperationParam(name = "message", type = StringType.class),
|
@OperationParam(name = "message", type = StringType.class),
|
||||||
@OperationParam(name = "display", type = StringType.class)
|
@OperationParam(name = "display", type = StringType.class)
|
||||||
})
|
})
|
||||||
public IBaseParameters validateCode(
|
public Parameters validateCode(
|
||||||
HttpServletRequest theServletRequest,
|
HttpServletRequest theServletRequest,
|
||||||
@IdParam(optional = true) IdType theId,
|
@IdParam(optional = true) IdType theId,
|
||||||
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
|
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
|
||||||
|
@ -99,25 +125,41 @@ public interface IValidationProvidersR4 {
|
||||||
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
|
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
|
||||||
@OperationParam(name = "valueSet") ValueSet theValueSet
|
@OperationParam(name = "valueSet") ValueSet theValueSet
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
String url = theValueSetUrl != null ? theValueSetUrl.getValue() : null;
|
mySystemUrl = theSystem;
|
||||||
String code = theCode != null ? theCode.getValue() : null;
|
myValueSetUrl = theValueSetUrl;
|
||||||
return getTerminologyResponse("$validate-code", url, code);
|
myCode = theCode;
|
||||||
|
myDisplay = theDisplay;
|
||||||
|
if (myException != null) {
|
||||||
|
throw myException;
|
||||||
|
}
|
||||||
|
return myReturnParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
return ValueSet.class;
|
return ValueSet.class;
|
||||||
}
|
}
|
||||||
@Override
|
public void setException(Exception theException) {
|
||||||
Class<Parameters> getParameterType() {
|
myException = theException;
|
||||||
return Parameters.class;
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ValueSet addTerminologyResource(String theUrl) {
|
public void setReturnParams(IBaseParameters theParameters) {
|
||||||
ValueSet valueSet = new ValueSet();
|
myReturnParams = (Parameters) theParameters;
|
||||||
valueSet.setId(theUrl.substring(0, theUrl.lastIndexOf("/")));
|
}
|
||||||
valueSet.setUrl(theUrl);
|
@Override
|
||||||
addTerminologyResource(theUrl, valueSet);
|
public String getCode() {
|
||||||
return valueSet;
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getValueSet() {
|
||||||
|
return myValueSetUrl != null ? myValueSetUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
public String getDisplay() {
|
||||||
|
return myDisplay != null ? myDisplay.getValue() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,10 +11,9 @@ import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersR4;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyLookupCodeTest;
|
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyLookupCodeTest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
@ -53,7 +52,7 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
private final RemoteTerminologyServiceValidationSupport mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx);
|
private final RemoteTerminologyServiceValidationSupport mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx);
|
||||||
private IValidationProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider;
|
private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider;
|
||||||
private MyLookupCodeProviderR4 myLookupCodeProviderR4;
|
private MyLookupCodeProviderR4 myLookupCodeProviderR4;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -61,7 +60,7 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
mySvc.setBaseUrl(baseUrl);
|
mySvc.setBaseUrl(baseUrl);
|
||||||
mySvc.addClientInterceptor(new LoggingInterceptor(true));
|
mySvc.addClientInterceptor(new LoggingInterceptor(true));
|
||||||
myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4();
|
myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4();
|
||||||
myLookupCodeProviderR4 = new MyLookupCodeProviderR4();
|
myLookupCodeProviderR4 = new MyLookupCodeProviderR4();
|
||||||
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myLookupCodeProviderR4);
|
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myLookupCodeProviderR4);
|
||||||
}
|
}
|
||||||
|
@ -167,6 +166,8 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
static class MyLookupCodeProviderR4 implements IValidationProviders.IMyLookupCodeProvider {
|
static class MyLookupCodeProviderR4 implements IValidationProviders.IMyLookupCodeProvider {
|
||||||
|
private UriType mySystemUrl;
|
||||||
|
private CodeType myCode;
|
||||||
private LookupCodeResult myLookupCodeResult;
|
private LookupCodeResult myLookupCodeResult;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -191,6 +192,8 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook
|
||||||
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<CodeType> thePropertyNames,
|
@OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List<CodeType> thePropertyNames,
|
||||||
RequestDetails theRequestDetails
|
RequestDetails theRequestDetails
|
||||||
) {
|
) {
|
||||||
|
myCode = theCode;
|
||||||
|
mySystemUrl = theSystem;
|
||||||
if (theSystem == null) {
|
if (theSystem == null) {
|
||||||
throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode));
|
throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode));
|
||||||
}
|
}
|
||||||
|
@ -203,5 +206,15 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
return CodeSystem.class;
|
return CodeSystem.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCode() {
|
||||||
|
return myCode != null ? myCode.getValueAsString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSystem() {
|
||||||
|
return mySystemUrl != null ? mySystemUrl.getValueAsString() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,12 @@ import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
import ca.uhn.fhir.context.support.LookupCodeRequest;
|
||||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersR4;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -16,15 +19,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_LOOKUP;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class RemoteTerminologyLookupCodeWithResponseFileR4Test {
|
public class RemoteTerminologyLookupCodeWithResponseFileR4Test {
|
||||||
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
private IValidationProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider;
|
private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider;
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ public class RemoteTerminologyLookupCodeWithResponseFileR4Test {
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
||||||
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
||||||
myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4();
|
myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4();
|
||||||
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider);
|
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +48,13 @@ public class RemoteTerminologyLookupCodeWithResponseFileR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void lookupCode_withParametersOutput_convertsCorrectly() {
|
void lookupCode_withParametersOutput_convertsCorrectly() {
|
||||||
String outputFile ="/terminology/CodeSystem-lookup-output-with-subproperties.json";
|
String paramsAsString = ClasspathUtil.loadResource("/terminology/CodeSystem-lookup-output-with-subproperties.json");
|
||||||
IBaseParameters resultParameters = myCodeSystemProvider.addTerminologyResponse(OPERATION_LOOKUP, CODE_SYSTEM, CODE, ourCtx, outputFile);
|
IBaseResource baseResource = ourCtx.newJsonParser().parseResource(paramsAsString);
|
||||||
|
assertTrue(baseResource instanceof Parameters);
|
||||||
|
Parameters resultParameters = (Parameters) baseResource;
|
||||||
|
myCodeSystemProvider.setReturnParams(resultParameters);
|
||||||
|
|
||||||
LookupCodeRequest request = new LookupCodeRequest(CODE_SYSTEM, CODE, null, List.of("interfaces"));
|
LookupCodeRequest request = new LookupCodeRequest(IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, null, List.of("interfaces"));
|
||||||
|
|
||||||
// test
|
// test
|
||||||
IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request);
|
IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request);
|
||||||
|
|
|
@ -2,8 +2,8 @@ package org.hl7.fhir.r4.validation;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
|
||||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||||
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||||
|
@ -13,11 +13,11 @@ import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProviders;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
import ca.uhn.fhir.test.utilities.validation.IValidationProvidersR4;
|
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyValidateCodeTest;
|
import org.hl7.fhir.common.hapi.validation.IRemoteTerminologyValidateCodeTest;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.IValidationProviders;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -39,12 +39,6 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.CODE_SYSTEM_VERSION;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.DISPLAY;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.ERROR_MESSAGE;
|
|
||||||
import static ca.uhn.fhir.test.utilities.validation.IValidationProviders.VALUE_SET_URL;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM;
|
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM;
|
||||||
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET;
|
import static org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport.ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET;
|
||||||
|
@ -67,8 +61,8 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx);
|
||||||
private IValidationProviders.IMyValidationProvider myCodeSystemProvider;
|
private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider;
|
||||||
private IValidationProviders.IMyValidationProvider myValueSetProvider;
|
private IValidateCodeProvidersR4.MyValueSetProviderR4 myValueSetProvider;
|
||||||
private RemoteTerminologyServiceValidationSupport mySvc;
|
private RemoteTerminologyServiceValidationSupport mySvc;
|
||||||
private String myCodeSystemError, myValueSetError;
|
private String myCodeSystemError, myValueSetError;
|
||||||
|
|
||||||
|
@ -77,14 +71,14 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort();
|
||||||
myCodeSystemError = ourCtx.getLocalizer().getMessage(
|
myCodeSystemError = ourCtx.getLocalizer().getMessage(
|
||||||
RemoteTerminologyServiceValidationSupport.class,
|
RemoteTerminologyServiceValidationSupport.class,
|
||||||
ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM, CODE_SYSTEM, CODE, baseUrl, ERROR_MESSAGE);
|
ERROR_CODE_UNKNOWN_CODE_IN_CODE_SYSTEM, IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, baseUrl, IValidationProviders.ERROR_MESSAGE);
|
||||||
myValueSetError = ourCtx.getLocalizer().getMessage(
|
myValueSetError = ourCtx.getLocalizer().getMessage(
|
||||||
RemoteTerminologyServiceValidationSupport.class,
|
RemoteTerminologyServiceValidationSupport.class,
|
||||||
ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET, CODE_SYSTEM, CODE, VALUE_SET_URL, baseUrl, ERROR_MESSAGE);
|
ERROR_CODE_UNKNOWN_CODE_IN_VALUE_SET, IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, IValidationProviders.VALUE_SET_URL, baseUrl, IValidationProviders.ERROR_MESSAGE);
|
||||||
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl);
|
||||||
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true));
|
||||||
myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4();
|
myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4();
|
||||||
myValueSetProvider = new IValidationProvidersR4.MyValueSetProviderR4();
|
myValueSetProvider = new IValidateCodeProvidersR4.MyValueSetProviderR4();
|
||||||
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider);
|
ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +95,12 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IValidationProviders.IMyValidationProvider getCodeSystemProvider() {
|
public IValidationProviders.IMyCodeSystemProvider getCodeSystemProvider() {
|
||||||
return myCodeSystemProvider;
|
return myCodeSystemProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IValidationProviders.IMyValidationProvider getValueSetProvider() {
|
public IValidationProviders.IMyValueSetProvider getValueSetProvider() {
|
||||||
return myValueSetProvider;
|
return myValueSetProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,40 +116,51 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() {
|
public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() {
|
||||||
return getCodeSystemInvalidCodeOutcome(OperationOutcome.class);
|
return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-CodeSystem-invalid-code.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseOperationOutcome getValueSetInvalidCodeOutcome() {
|
public IBaseOperationOutcome getValueSetInvalidCodeOutcome() {
|
||||||
return getValueSetInvalidCodeOutcome(OperationOutcome.class);
|
return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-ValueSet-invalid-code.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseOperationOutcome getValueSetCustomDetailCodeOutcome() {
|
public List<IValidationSupport.CodeValidationIssue> getCodeValidationIssues(IBaseOperationOutcome theOperationOutcome) {
|
||||||
return getValueSetCustomDetailCodeOutcome(OperationOutcome.class);
|
return ((OperationOutcome)theOperationOutcome).getIssue().stream()
|
||||||
|
.map(issueComponent -> new IValidationSupport.CodeValidationIssue(
|
||||||
|
issueComponent.getDetails().getText(),
|
||||||
|
IValidationSupport.IssueSeverity.ERROR,
|
||||||
|
/* assume issue type is OperationOutcome.IssueType#CODEINVALID as it is the only match */
|
||||||
|
IValidationSupport.CodeValidationIssueCode.INVALID,
|
||||||
|
IValidationSupport.CodeValidationIssueCoding.INVALID_CODE))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateCodeInValueSet_success() {
|
void validateCodeInValueSet_success() {
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null, new ConceptValidationOptions(), CODE_SYSTEM, CODE, DISPLAY, valueSet);
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null, new ConceptValidationOptions(), IValidationProviders.CODE_SYSTEM, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
assertNotNull(outcome);
|
assertNotNull(outcome);
|
||||||
assertEquals(CODE, outcome.getCode());
|
assertEquals(IValidationProviders.CODE, outcome.getCode());
|
||||||
assertEquals(DISPLAY, outcome.getDisplay());
|
assertEquals(IValidationProviders.DISPLAY, outcome.getDisplay());
|
||||||
assertNull(outcome.getSeverity());
|
assertNull(outcome.getSeverity());
|
||||||
assertNull(outcome.getMessage());
|
assertNull(outcome.getMessage());
|
||||||
|
|
||||||
|
assertEquals(IValidationProviders.CODE, myValueSetProvider.getCode());
|
||||||
|
assertEquals(IValidationProviders.DISPLAY, myValueSetProvider.getDisplay());
|
||||||
|
assertEquals(IValidationProviders.VALUE_SET_URL, myValueSetProvider.getValueSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) {
|
||||||
Parameters parameters = new Parameters()
|
Parameters parameters = new Parameters()
|
||||||
.addParameter("code", CODE)
|
.addParameter("code", IValidationProviders.CODE)
|
||||||
.addParameter("system", CODE_SYSTEM)
|
.addParameter("system", IValidationProviders.CODE_SYSTEM)
|
||||||
.addParameter("version", CODE_SYSTEM_VERSION)
|
.addParameter("version", IValidationProviders.CODE_SYSTEM_VERSION)
|
||||||
.addParameter("display", theDisplay)
|
.addParameter("display", theDisplay)
|
||||||
.addParameter("message", theMessage);
|
.addParameter("message", theMessage);
|
||||||
if (theResult != null) {
|
if (theResult != null) {
|
||||||
|
@ -176,16 +181,16 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateCodeInValueSet_uniqueComposeInclude() {
|
void validateCodeInValueSet_uniqueComposeInclude() {
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
||||||
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
||||||
Collections.singletonList(new ValueSet.ConceptSetComponent().setSystem(systemUrl)) ));
|
Collections.singletonList(new ValueSet.ConceptSetComponent().setSystem(systemUrl)) ));
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
||||||
new ConceptValidationOptions().setInferSystem(true), null, CODE, DISPLAY, valueSet);
|
new ConceptValidationOptions().setInferSystem(true), null, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
|
|
||||||
// validate service doesn't return error message (as when no code system is present)
|
// validate service doesn't return error message (as when no code system is present)
|
||||||
assertNotNull(outcome);
|
assertNotNull(outcome);
|
||||||
|
@ -206,16 +211,16 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource(value = "getRemoteTerminologyServerExceptions")
|
@MethodSource(value = "getRemoteTerminologyServerExceptions")
|
||||||
void validateCodeInValueSet_systemNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) {
|
void validateCodeInValueSet_systemNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) {
|
||||||
getValueSetProvider().addException("$validate-code", VALUE_SET_URL, CODE, theException);
|
myValueSetProvider.setException(theException);
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
||||||
Lists.newArrayList(new ValueSet.ConceptSetComponent(), new ValueSet.ConceptSetComponent())));
|
Lists.newArrayList(new ValueSet.ConceptSetComponent(), new ValueSet.ConceptSetComponent())));
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
||||||
new ConceptValidationOptions().setInferSystem(true), null, CODE, DISPLAY, valueSet);
|
new ConceptValidationOptions().setInferSystem(true), null, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
|
|
||||||
String unknownCodeForValueSetError = "Unknown code \"null#CODE\" for ValueSet with URL \"http://value.set/url\". The Remote Terminology server http://";
|
String unknownCodeForValueSetError = "Unknown code \"null#CODE\" for ValueSet with URL \"http://value.set/url\". The Remote Terminology server http://";
|
||||||
verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage);
|
verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage);
|
||||||
|
@ -225,11 +230,11 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource(value = "getRemoteTerminologyServerExceptions")
|
@MethodSource(value = "getRemoteTerminologyServerExceptions")
|
||||||
void validateCodeInValueSet_systemPresentCodeNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) {
|
void validateCodeInValueSet_systemPresentCodeNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) {
|
||||||
getValueSetProvider().addException(JpaConstants.OPERATION_VALIDATE_CODE, VALUE_SET_URL, CODE, theException);
|
myValueSetProvider.setException(theException);
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
||||||
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
||||||
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
||||||
|
@ -238,7 +243,7 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
new ValueSet.ConceptSetComponent().setSystem(systemUrl2))));
|
new ValueSet.ConceptSetComponent().setSystem(systemUrl2))));
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
||||||
new ConceptValidationOptions().setInferSystem(true), null, CODE, DISPLAY, valueSet);
|
new ConceptValidationOptions().setInferSystem(true), null, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
|
|
||||||
String unknownCodeForValueSetError = "Unknown code \"null#CODE\" for ValueSet with URL \"http://value.set/url\". The Remote Terminology server http://";
|
String unknownCodeForValueSetError = "Unknown code \"null#CODE\" for ValueSet with URL \"http://value.set/url\". The Remote Terminology server http://";
|
||||||
verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage);
|
verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage);
|
||||||
|
@ -247,10 +252,10 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateCodeInValueSet_systemPresentCodePresentValidatesOKNoVersioned() {
|
void validateCodeInValueSet_systemPresentCodePresentValidatesOKNoVersioned() {
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
||||||
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
||||||
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude(
|
||||||
|
@ -259,14 +264,14 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
new ValueSet.ConceptSetComponent().setSystem(systemUrl2).setConcept(
|
new ValueSet.ConceptSetComponent().setSystem(systemUrl2).setConcept(
|
||||||
Lists.newArrayList(
|
Lists.newArrayList(
|
||||||
new ValueSet.ConceptReferenceComponent().setCode("not-the-code"),
|
new ValueSet.ConceptReferenceComponent().setCode("not-the-code"),
|
||||||
new ValueSet.ConceptReferenceComponent().setCode(CODE) )
|
new ValueSet.ConceptReferenceComponent().setCode(IValidationProviders.CODE) )
|
||||||
)) ));
|
)) ));
|
||||||
|
|
||||||
TestClientInterceptor requestInterceptor = new TestClientInterceptor();
|
TestClientInterceptor requestInterceptor = new TestClientInterceptor();
|
||||||
mySvc.addClientInterceptor(requestInterceptor);
|
mySvc.addClientInterceptor(requestInterceptor);
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
||||||
new ConceptValidationOptions().setInferSystem(true), null, CODE, DISPLAY, valueSet);
|
new ConceptValidationOptions().setInferSystem(true), null, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
|
|
||||||
assertNotNull(outcome);
|
assertNotNull(outcome);
|
||||||
assertEquals(systemUrl2, requestInterceptor.getCapturedSystemParameter());
|
assertEquals(systemUrl2, requestInterceptor.getCapturedSystemParameter());
|
||||||
|
@ -275,10 +280,10 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateCodeInValueSet_systemPresentCodePresentValidatesOKVersioned() {
|
void validateCodeInValueSet_systemPresentCodePresentValidatesOKVersioned() {
|
||||||
createValueSetReturnParameters(true, DISPLAY, null, null);
|
createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null);
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
valueSet.setUrl(VALUE_SET_URL);
|
valueSet.setUrl(IValidationProviders.VALUE_SET_URL);
|
||||||
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender";
|
||||||
String systemVersion = "3.0.2";
|
String systemVersion = "3.0.2";
|
||||||
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
String systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset";
|
||||||
|
@ -289,14 +294,14 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa
|
||||||
new ValueSet.ConceptSetComponent().setSystem(systemUrl2).setVersion(system2Version).setConcept(
|
new ValueSet.ConceptSetComponent().setSystem(systemUrl2).setVersion(system2Version).setConcept(
|
||||||
Lists.newArrayList(
|
Lists.newArrayList(
|
||||||
new ValueSet.ConceptReferenceComponent().setCode("not-the-code"),
|
new ValueSet.ConceptReferenceComponent().setCode("not-the-code"),
|
||||||
new ValueSet.ConceptReferenceComponent().setCode(CODE) )
|
new ValueSet.ConceptReferenceComponent().setCode(IValidationProviders.CODE) )
|
||||||
)) ));
|
)) ));
|
||||||
|
|
||||||
TestClientInterceptor requestInterceptor = new TestClientInterceptor();
|
TestClientInterceptor requestInterceptor = new TestClientInterceptor();
|
||||||
mySvc.addClientInterceptor(requestInterceptor);
|
mySvc.addClientInterceptor(requestInterceptor);
|
||||||
|
|
||||||
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
CodeValidationResult outcome = mySvc.validateCodeInValueSet(null,
|
||||||
new ConceptValidationOptions().setInferSystem(true), null, CODE, DISPLAY, valueSet);
|
new ConceptValidationOptions().setInferSystem(true), null, IValidationProviders.CODE, IValidationProviders.DISPLAY, valueSet);
|
||||||
|
|
||||||
assertNotNull(outcome);
|
assertNotNull(outcome);
|
||||||
assertEquals(systemUrl2 + "|" + system2Version, requestInterceptor.getCapturedSystemParameter());
|
assertEquals(systemUrl2 + "|" + system2Version, requestInterceptor.getCapturedSystemParameter());
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4b.conformance.ProfileUtilities;
|
import org.hl7.fhir.r4b.conformance.ProfileUtilities;
|
||||||
import org.hl7.fhir.r4b.context.IWorkerContext;
|
import org.hl7.fhir.r4b.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r4b.fhirpath.FHIRPathEngine;
|
|
||||||
import org.hl7.fhir.r4b.hapi.ctx.HapiWorkerContext;
|
import org.hl7.fhir.r4b.hapi.ctx.HapiWorkerContext;
|
||||||
import org.hl7.fhir.r4b.model.AllergyIntolerance;
|
import org.hl7.fhir.r4b.model.AllergyIntolerance;
|
||||||
import org.hl7.fhir.r4b.model.Base;
|
import org.hl7.fhir.r4b.model.Base;
|
||||||
|
@ -62,6 +61,7 @@ import org.hl7.fhir.r4b.model.StructureDefinition.StructureDefinitionKind;
|
||||||
import org.hl7.fhir.r4b.model.ValueSet;
|
import org.hl7.fhir.r4b.model.ValueSet;
|
||||||
import org.hl7.fhir.r4b.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r4b.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r4b.terminologies.ValueSetExpander;
|
import org.hl7.fhir.r4b.terminologies.ValueSetExpander;
|
||||||
|
import org.hl7.fhir.r4b.fhirpath.FHIRPathEngine;
|
||||||
import org.hl7.fhir.r5.test.utils.ClassesLoadedFlags;
|
import org.hl7.fhir.r5.test.utils.ClassesLoadedFlags;
|
||||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||||
|
@ -203,7 +203,7 @@ public class FhirInstanceValidatorR4BTest extends BaseValidationTestWithInlineMo
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
||||||
} else if (myValidSystems.contains(system)) {
|
} else if (myValidSystems.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
return new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message).setIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
return new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message).setCodeValidationIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(message, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
||||||
} else {
|
} else {
|
||||||
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||||
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
||||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -199,10 +200,10 @@ public class FhirInstanceValidatorR5Test extends BaseValidationTestWithInlineMoc
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
retVal = new IValidationSupport.CodeValidationResult().setCode(code);
|
||||||
} else if (myValidSystems.contains(system)) {
|
} else if (myValidSystems.contains(system)) {
|
||||||
String theMessage = "Unknown code (for '" + system + "#" + code + "')";
|
String theMessage = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(theMessage).setIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(theMessage, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(theMessage).setCodeValidationIssues(Collections.singletonList(new IValidationSupport.CodeValidationIssue(theMessage, IValidationSupport.IssueSeverity.ERROR, IValidationSupport.CodeValidationIssueCode.CODE_INVALID, IValidationSupport.CodeValidationIssueCoding.INVALID_CODE)));
|
||||||
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
} else if (myValidSystemsNotReturningIssues.contains(system)) {
|
||||||
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
final String message = "Unknown code (for '" + system + "#" + code + "')";
|
||||||
retVal = new IValidationSupport.CodeValidationResult().setSeverity(IValidationSupport.IssueSeverity.ERROR).setMessage(message);
|
retVal = new IValidationSupport.CodeValidationResult().setSeverityCode(ValidationMessage.IssueSeverity.ERROR.toCode()).setMessage(message);
|
||||||
} else {
|
} else {
|
||||||
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"resourceType": "OperationOutcome",
|
|
||||||
"issue": [
|
|
||||||
{
|
|
||||||
"severity": "information",
|
|
||||||
"code": "processing",
|
|
||||||
"details": {
|
|
||||||
"coding": [
|
|
||||||
{
|
|
||||||
"system": "http://example.com/custom-issue-type",
|
|
||||||
"code": "valueset-is-draft"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"diagnostics": "The ValueSet status is marked as draft.",
|
|
||||||
"location": [
|
|
||||||
"Bundle",
|
|
||||||
"Line[1] Col[2]"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in New Issue