From 9365ad9509a0cf1c7d6dc228dba7470dd78c188a Mon Sep 17 00:00:00 2001 From: Tadgh Date: Tue, 5 Nov 2024 09:14:18 -0800 Subject: [PATCH] =?UTF-8?q?Revert=20"Fixes=20for=20the=20translation=20of?= =?UTF-8?q?=20parameter=20issues=20as=20part=20of=20the=20output=20f?= =?UTF-8?q?=E2=80=A6"=20(#6441)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fca3ea444593175b5187525ec33cbb56142d1383. --- .../context/support/IValidationSupport.java | 303 +++--------------- .../6422-fixes-remote-terminology-issues.yaml | 7 - .../ca/uhn/fhir/jpa/term/TermReadSvcImpl.java | 5 +- ...OperationWithRemoteTerminologyR4Test.java} | 167 +++++++--- .../ValidateWithRemoteTerminologyTest.java | 261 --------------- .../encounter/profile-encounter-custom.json | 49 --- ...idateCode-CodeSystem-encounter-status.json | 59 ---- .../validateCode-CodeSystem-v2-0203.json | 25 -- .../validateCode-CodeSystem-v3-ActCode.json | 46 --- ...alidateCode-ValueSet-encounter-status.json | 59 ---- ...validateCode-ValueSet-identifier-type.json | 52 --- ...dateCode-ValueSet-v3-ActEncounterCode.json | 59 ---- .../validateCode-CodeSystem-ICD9CM.json | 48 --- ...ateCode-CodeSystem-observation-status.json | 25 -- .../validateCode-ValueSet-codes.json | 48 --- ...idateCode-ValueSet-observation-status.json | 25 -- .../procedure/profile-procedure-slicing.json | 79 ----- .../procedure/profile-procedure.json | 50 --- ...dateCode-CodeSystem-absent-or-unknown.json | 46 --- .../validateCode-CodeSystem-event-status.json | 59 ---- ...alidateCode-CodeSystem-snomed-invalid.json | 48 --- .../validateCode-CodeSystem-snomed-valid.json | 25 -- ...-ValueSet-absent-or-unknown-procedure.json | 59 ---- .../validateCode-ValueSet-event-status.json | 25 -- ...ValueSet-procedure-code-invalid-slice.json | 48 --- ...eCode-ValueSet-procedure-code-invalid.json | 67 ---- ...ateCode-ValueSet-procedure-code-valid.json | 59 ---- .../validation/IValidationProviders.java | 104 ------ .../validation/IValidationProvidersDstu3.java | 118 ------- .../CommonCodeSystemsTerminologyService.java | 2 +- ...oryTerminologyServerValidationSupport.java | 35 +- ...teTerminologyServiceValidationSupport.java | 36 +-- ...ownCodeSystemWarningValidationSupport.java | 2 +- .../support/ValidationSupportUtils.java | 11 - .../VersionSpecificWorkerContextWrapper.java | 105 ++++-- .../hapi/validation/ILookupCodeTest.java | 15 +- .../IRemoteTerminologyLookupCodeTest.java | 1 - .../IRemoteTerminologyValidateCodeTest.java | 59 ---- .../hapi/validation/IValidateCodeTest.java | 146 ++++----- .../hapi/validation/IValidationProviders.java | 39 +++ ...rsionSpecificWorkerContextWrapperTest.java | 31 +- .../FhirInstanceValidatorDstu2Test.java | 8 +- .../FhirInstanceValidatorDstu3Test.java | 5 +- .../IValidateCodeProvidersDstu3.java | 159 +++++++++ ...estionnaireResponseValidatorDstu3Test.java | 9 +- .../RemoteTerminologyLookupCodeDstu3Test.java | 16 +- ...gyLookupCodeWithResponseFileDstu3Test.java | 22 +- ...emoteTerminologyValidateCodeDstu3Test.java | 52 ++- .../FhirInstanceValidatorR4Test.java | 4 +- .../validation/IValidateCodeProvidersR4.java | 116 ++++--- .../RemoteTerminologyLookupCodeR4Test.java | 21 +- ...ologyLookupCodeWithResponseFileR4Test.java | 22 +- .../RemoteTerminologyValidateCodeR4Test.java | 101 +++--- .../FhirInstanceValidatorR4BTest.java | 4 +- .../FhirInstanceValidatorR5Test.java | 5 +- ...nOutcome-ValueSet-custom-issue-detail.json | 22 -- 56 files changed, 774 insertions(+), 2299 deletions(-) delete mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6422-fixes-remote-terminology-issues.yaml rename hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/{validation/ValidateCodeWithRemoteTerminologyR4Test.java => provider/r4/ValidateCodeOperationWithRemoteTerminologyR4Test.java} (59%) delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateWithRemoteTerminologyTest.java delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/profile-encounter-custom.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-encounter-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v2-0203.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v3-ActCode.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-encounter-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-identifier-type.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-v3-ActEncounterCode.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-ICD9CM.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-observation-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-codes.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-observation-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure-slicing.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-absent-or-unknown.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-event-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-invalid.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-valid.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-absent-or-unknown-procedure.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-event-status.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid-slice.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid.json delete mode 100644 hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-valid.json delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProviders.java delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersDstu3.java create mode 100644 hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidationProviders.java create mode 100644 hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/IValidateCodeProvidersDstu3.java rename hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersR4.java => hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/IValidateCodeProvidersR4.java (55%) delete mode 100644 hapi-fhir-validation/src/test/resources/terminology/OperationOutcome-ValueSet-custom-issue-detail.json diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java index fdbc4ca31d7..71d561c1db3 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java @@ -440,259 +440,74 @@ public interface IValidationSupport { return "Unknown " + getFhirContext().getVersion().getVersion() + " Validation Support"; } - /** - * Defines codes in system http://hl7.org/fhir/issue-severity. - */ - /* this enum would not be needed if we design/refactor to use org.hl7.fhir.r5.terminologies.utilities.ValidationResult */ enum IssueSeverity { /** * 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. */ - 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. */ - WARNING("warning"), + WARNING, /** * The issue has no relation to the degree of success of the action. */ - 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 http://hl7.org/fhir/issue-severity. - * @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; - } - } + INFORMATION } - /** - * Defines codes in system http://hl7.org/fhir/issue-type. - * The binding is enforced as a part of validation logic in the FHIR Core Validation library where an exception is thrown. - * Only a sub-set of these codes are defined as constants because they relate to validation, - * If there are additional ones that come up, for Remote Terminology they are currently supported via - * {@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 http://hl7.org/fhir/issue-type. - * @return the code - */ - public String getCode() { - return myCode; - } + enum CodeValidationIssueCode { + NOT_FOUND, + CODE_INVALID, + INVALID, + OTHER } - /** - * Holds information about the details of a {@link CodeValidationIssue}. - * This maps to resource OperationOutcome.issue.details. - */ - /* 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 myCodings; + enum CodeValidationIssueCoding { + VS_INVALID, + NOT_FOUND, + NOT_IN_VS, - public CodeValidationIssueDetails(String theText) { - myText = theText; - } - - // 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 getCodings() { - if (myCodings == null) { - myCodings = new ArrayList<>(); - } - return myCodings; - } + INVALID_CODE, + INVALID_DISPLAY, + OTHER } - /** - * Defines codes that can be part of the details of an issue. - * There are some constants available (pre-defined) for codes for system http://hl7.org/fhir/tools/CodeSystem/tx-issue-type. - * 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 { - private final String myDiagnostics; + + private final String myMessage; private final IssueSeverity mySeverity; private final CodeValidationIssueCode myCode; - private CodeValidationIssueDetails myDetails; + private final CodeValidationIssueCoding myCoding; public CodeValidationIssue( - String theDiagnostics, IssueSeverity theSeverity, CodeValidationIssueCode theTypeCode) { - this(theDiagnostics, theSeverity, theTypeCode, null); + String theMessage, + 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() { - return getDiagnostics(); - } - - public String getDiagnostics() { - return myDiagnostics; + return myMessage; } public IssueSeverity getSeverity() { return mySeverity; } - /** - * @deprecated Please use {@link #getType()} instead. - */ - @Deprecated(since = "7.4.6") public CodeValidationIssueCode getCode() { - return getType(); - } - - public CodeValidationIssueCode getType() { return myCode; } - /** - * @deprecated Please use {@link #getDetails()} instead. That has support for multiple codings. - */ - @Deprecated(since = "7.4.6") public CodeValidationIssueCoding getCoding() { - return myDetails != null - ? 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())); + return myCoding; } } @@ -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 { public static final String SOURCE_DETAILS = "sourceDetails"; public static final String RESULT = "result"; @@ -875,7 +686,7 @@ public interface IValidationSupport { private String myDisplay; private String mySourceDetails; - private List myIssues; + private List myCodeValidationIssues; public CodeValidationResult() { super(); @@ -960,48 +771,23 @@ public interface IValidationSupport { return this; } - /** - * @deprecated Please use method {@link #getIssues()} instead. - */ - @Deprecated(since = "7.4.6") public List 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 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) { getCodeValidationIssues().add(theCodeValidationIssue); return this; } - public List getIssues() { - if (myIssues == null) { - myIssues = new ArrayList<>(); - } - return myIssues; - } - - public CodeValidationResult setIssues(List theIssues) { - myIssues = new ArrayList<>(theIssues); - return this; - } - - public CodeValidationResult addIssue(CodeValidationIssue theCodeValidationIssue) { - getIssues().add(theCodeValidationIssue); - return this; - } - public boolean isOk() { return isNotBlank(myCode); } @@ -1025,19 +811,17 @@ public interface IValidationSupport { public String getSeverityCode() { String retVal = null; if (getSeverity() != null) { - retVal = getSeverity().getCode(); + retVal = getSeverity().name().toLowerCase(); } return retVal; } /** - * Sets an issue severity using a severity code. Please use method {@link #setSeverity(IssueSeverity)} instead. - * @param theSeverityCode the code - * @return the current {@link CodeValidationResult} instance + * Sets an issue severity as a string code. Value must be the name of + * one of the enum values in {@link IssueSeverity}. Value is case-insensitive. */ - @Deprecated(since = "7.4.6") - public CodeValidationResult setSeverityCode(@Nonnull String theSeverityCode) { - setSeverity(IssueSeverity.fromCode(theSeverityCode)); + public CodeValidationResult setSeverityCode(@Nonnull String theIssueSeverity) { + setSeverity(IssueSeverity.valueOf(theIssueSeverity.toUpperCase())); return this; } @@ -1054,11 +838,6 @@ public interface IValidationSupport { if (isNotBlank(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; } diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6422-fixes-remote-terminology-issues.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6422-fixes-remote-terminology-issues.yaml deleted file mode 100644 index 9b6dc6320ce..00000000000 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6422-fixes-remote-terminology-issues.yaml +++ /dev/null @@ -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." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java index f443a55be83..e9f07b798a5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcImpl.java @@ -1044,8 +1044,7 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs { if (theExpansionOptions != null && !theExpansionOptions.isFailOnMissingCodeSystem() // Code system is unknown, therefore NOT_FOUND - && e.getCodeValidationIssue() - .hasIssueDetailCode(CodeValidationIssueCoding.NOT_FOUND.getCode())) { + && e.getCodeValidationIssue().getCoding() == CodeValidationIssueCoding.NOT_FOUND) { return; } throw new InternalErrorException(Msg.code(888) + e); @@ -2191,7 +2190,7 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs { .setSeverity(IssueSeverity.ERROR) .setCodeSystemVersion(theCodeSystemVersion) .setMessage(theMessage) - .addIssue(new CodeValidationIssue( + .addCodeValidationIssue(new CodeValidationIssue( theMessage, IssueSeverity.ERROR, CodeValidationIssueCode.CODE_INVALID, diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateCodeWithRemoteTerminologyR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ValidateCodeOperationWithRemoteTerminologyR4Test.java similarity index 59% rename from hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateCodeWithRemoteTerminologyR4Test.java rename to hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ValidateCodeOperationWithRemoteTerminologyR4Test.java index 3787c611eb7..4da204217f0 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateCodeWithRemoteTerminologyR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ValidateCodeOperationWithRemoteTerminologyR4Test.java @@ -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.jpa.config.JpaConfig; import ca.uhn.fhir.jpa.model.util.JpaConstants; 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.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 org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport; 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.CodeSystem; import org.hl7.fhir.r4.model.CodeType; 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.StringType; import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.ValueSet; 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.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.AssertionsForClassTypes.assertThatExceptionOfType; 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.fail; -/** +/* * This set of integration tests that instantiates and injects an instance of * {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport} * 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 - * {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport} + * implementation. It also exercises the code found in + * {@link org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport#invokeRemoteValidateCode} */ -public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProviderR4Test { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateCodeWithRemoteTerminologyR4Test.class); +public class ValidateCodeOperationWithRemoteTerminologyR4Test extends BaseResourceProviderR4Test { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateCodeOperationWithRemoteTerminologyR4Test.class); private static final String DISPLAY = "DISPLAY"; private static final String DISPLAY_BODY_MASS_INDEX = "Body mass index (BMI) [Ratio]"; 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); private RemoteTerminologyServiceValidationSupport mySvc; - private IValidationProviders.MyValidationProvider myCodeSystemProvider; - private IValidationProviders.MyValidationProvider myValueSetProvider; + private MyCodeSystemProvider myCodeSystemProvider; + private MyValueSetProvider myValueSetProvider; @Autowired @Qualifier(JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN) @@ -66,8 +76,8 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl); myValidationSupportChain.addValidationSupport(0, mySvc); - myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4(); - myValueSetProvider = new IValidationProvidersR4.MyValueSetProviderR4(); + myCodeSystemProvider = new MyCodeSystemProvider(); + myValueSetProvider = new MyValueSetProvider(); ourRestfulServerExtension.registerProvider(myCodeSystemProvider); ourRestfulServerExtension.registerProvider(myValueSetProvider); } @@ -93,11 +103,11 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide @Test public void validateCodeOperationOnCodeSystem_byCodingAndUrl_usingBuiltInCodeSystems() { - final String code = "P"; - final String system = CODE_SYSTEM_V2_0247_URI;; - - Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY); - setupCodeSystemValidateCode(system, code, params); + myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>(); + myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/v2-0247")); + myCodeSystemProvider.myReturnParams = new Parameters(); + myCodeSystemProvider.myReturnParams.addParameter("result", true); + myCodeSystemProvider.myReturnParams.addParameter("display", DISPLAY); logAllConcepts(); @@ -105,8 +115,8 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide .operation() .onType(CodeSystem.class) .named(JpaConstants.OPERATION_VALIDATE_CODE) - .withParameter(Parameters.class, "coding", new Coding().setSystem(system).setCode(code)) - .andParameter("url", new UriType(system)) + .withParameter(Parameters.class, "coding", new Coding().setSystem(CODE_SYSTEM_V2_0247_URI).setCode("P")) + .andParameter("url", new UriType(CODE_SYSTEM_V2_0247_URI)) .execute(); String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); @@ -118,7 +128,7 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide @Test public void validateCodeOperationOnCodeSystem_byCodingAndUrlWhereCodeSystemIsUnknown_returnsFalse() { - myCodeSystemProvider.setShouldThrowExceptionForResourceNotFound(false); + myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>(); Parameters respParam = myClient .operation() @@ -156,21 +166,21 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide @Test public void validateCodeOperationOnValueSet_byUrlAndSystem_usingBuiltInCodeSystems() { - final String code = "alerts"; - final String system = "http://terminology.hl7.org/CodeSystem/list-example-use-codes"; - final String valueSetUrl = "http://hl7.org/fhir/ValueSet/list-example-codes"; - - Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY); - setupValueSetValidateCode(valueSetUrl, system, code, params); - setupCodeSystemValidateCode(system, code, params); + myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>(); + myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/list-example-use-codes")); + myValueSetProvider.myReturnValueSets = new ArrayList<>(); + myValueSetProvider.myReturnValueSets.add((ValueSet) new ValueSet().setId("ValueSet/list-example-codes")); + myValueSetProvider.myReturnParams = new Parameters(); + myValueSetProvider.myReturnParams.addParameter("result", true); + myValueSetProvider.myReturnParams.addParameter("display", DISPLAY); Parameters respParam = myClient .operation() .onType(ValueSet.class) .named(JpaConstants.OPERATION_VALIDATE_CODE) - .withParameter(Parameters.class, "code", new CodeType(code)) - .andParameter("system", new UriType(system)) - .andParameter("url", new UriType(valueSetUrl)) + .withParameter(Parameters.class, "code", new CodeType("alerts")) + .andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/list-example-use-codes")) + .andParameter("url", new UriType("http://hl7.org/fhir/ValueSet/list-example-codes")) .useHttpGet() .execute(); @@ -183,20 +193,21 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide @Test public void validateCodeOperationOnValueSet_byUrlSystemAndCode() { - final String code = CODE_BODY_MASS_INDEX; - final String system = "http://terminology.hl7.org/CodeSystem/list-example-use-codes"; - final String valueSetUrl = "http://hl7.org/fhir/ValueSet/list-example-codes"; - - Parameters params = new Parameters().addParameter("result", true).addParameter("display", DISPLAY_BODY_MASS_INDEX); - setupValueSetValidateCode(valueSetUrl, system, code, params); + myCodeSystemProvider.myReturnCodeSystems = new ArrayList<>(); + myCodeSystemProvider.myReturnCodeSystems.add((CodeSystem) new CodeSystem().setId("CodeSystem/list-example-use-codes")); + myValueSetProvider.myReturnValueSets = new ArrayList<>(); + myValueSetProvider.myReturnValueSets.add((ValueSet) new ValueSet().setId("ValueSet/list-example-codes")); + myValueSetProvider.myReturnParams = new Parameters(); + myValueSetProvider.myReturnParams.addParameter("result", true); + myValueSetProvider.myReturnParams.addParameter("display", DISPLAY_BODY_MASS_INDEX); Parameters respParam = myClient .operation() .onType(ValueSet.class) .named(JpaConstants.OPERATION_VALIDATE_CODE) - .withParameter(Parameters.class, "code", new CodeType(code)) - .andParameter("url", new UriType(valueSetUrl)) - .andParameter("system", new UriType(system)) + .withParameter(Parameters.class, "code", new CodeType(CODE_BODY_MASS_INDEX)) + .andParameter("url", new UriType("https://loinc.org")) + .andParameter("system", new UriType("http://loinc.org")) .execute(); String resp = myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); @@ -208,7 +219,7 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide @Test public void validateCodeOperationOnValueSet_byCodingAndUrlWhereValueSetIsUnknown_returnsFalse() { - myValueSetProvider.setShouldThrowExceptionForResourceNotFound(false); + myValueSetProvider.myReturnValueSets = new ArrayList<>(); Parameters respParam = myClient .operation() @@ -227,18 +238,70 @@ public class ValidateCodeWithRemoteTerminologyR4Test extends BaseResourceProvide " - Unknown or unusable ValueSet[" + UNKNOWN_VALUE_SYSTEM_URI + "]"); } - private void setupValueSetValidateCode(String theUrl, String theSystem, String theCode, IBaseParameters theResponseParams) { - ValueSet valueSet = myValueSetProvider.addTerminologyResource(theUrl); - myValueSetProvider.addTerminologyResource(theSystem); - myValueSetProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, valueSet.getUrl(), theCode, theResponseParams); + @SuppressWarnings("unused") + private static class MyCodeSystemProvider implements IResourceProvider { + private List myReturnCodeSystems; + private Parameters myReturnParams; - // 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); + @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 theCodeSystemUrl, + @OperationParam(name = "code", min = 0, max = 1) CodeType theCode, + @OperationParam(name = "display", min = 0, max = 1) StringType theDisplay + ) { + return myReturnParams; + } + + @Search + public List find(@RequiredParam(name = "url") UriParam theUrlParam) { + assert myReturnCodeSystems != null; + return myReturnCodeSystems; + } + + @Override + public Class getResourceType() { + return CodeSystem.class; + } } - private void setupCodeSystemValidateCode(String theUrl, String theCode, IBaseParameters theResponseParams) { - CodeSystem codeSystem = myCodeSystemProvider.addTerminologyResource(theUrl); - myCodeSystemProvider.addTerminologyResponse(OPERATION_VALIDATE_CODE, codeSystem.getUrl(), theCode, theResponseParams); + @SuppressWarnings("unused") + private static class MyValueSetProvider implements IResourceProvider { + private Parameters myReturnParams; + private List 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 find(@RequiredParam(name = "url") UriParam theUrlParam) { + assert myReturnValueSets != null; + return myReturnValueSets; + } + + @Override + public Class getResourceType() { + return ValueSet.class; + } + } } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateWithRemoteTerminologyTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateWithRemoteTerminologyTest.java deleted file mode 100644 index 79a656db39c..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/validation/ValidateWithRemoteTerminologyTest.java +++ /dev/null @@ -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. OntoServer. - * 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 myCodeSystemProvider; - private IValidationProviders.MyValidationProvider 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 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 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 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 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 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(); - } -} diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/profile-encounter-custom.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/profile-encounter-custom.json deleted file mode 100644 index a553a61a1c2..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/profile-encounter-custom.json +++ /dev/null @@ -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 - } - ] - } -} diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-encounter-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-encounter-status.json deleted file mode 100644 index 2399dc870ec..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-encounter-status.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v2-0203.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v2-0203.json deleted file mode 100644 index 10747c14ee3..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v2-0203.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v3-ActCode.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v3-ActCode.json deleted file mode 100644 index b692847e0fb..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-CodeSystem-v3-ActCode.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-encounter-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-encounter-status.json deleted file mode 100644 index 2399dc870ec..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-encounter-status.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-identifier-type.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-identifier-type.json deleted file mode 100644 index b0767dc2f18..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-identifier-type.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-v3-ActEncounterCode.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-v3-ActEncounterCode.json deleted file mode 100644 index 083dbffae43..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/encounter/validateCode-ValueSet-v3-ActEncounterCode.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-ICD9CM.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-ICD9CM.json deleted file mode 100644 index 831ac6660fa..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-ICD9CM.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-observation-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-observation-status.json deleted file mode 100644 index 7914321876c..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-CodeSystem-observation-status.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-codes.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-codes.json deleted file mode 100644 index 4571362033f..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-codes.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-observation-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-observation-status.json deleted file mode 100644 index 7914321876c..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/observation/validateCode-ValueSet-observation-status.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure-slicing.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure-slicing.json deleted file mode 100644 index 8bc05c70cf0..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure-slicing.json +++ /dev/null @@ -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 - } - ] - } -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure.json deleted file mode 100644 index 5315694dece..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/profile-procedure.json +++ /dev/null @@ -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 - } - ] - } -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-absent-or-unknown.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-absent-or-unknown.json deleted file mode 100644 index 4d7b20f0881..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-absent-or-unknown.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-event-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-event-status.json deleted file mode 100644 index 620624a991e..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-event-status.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-invalid.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-invalid.json deleted file mode 100644 index f6a86048d6e..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-invalid.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-valid.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-valid.json deleted file mode 100644 index a602bfda9f0..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-CodeSystem-snomed-valid.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-absent-or-unknown-procedure.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-absent-or-unknown-procedure.json deleted file mode 100644 index aaee02a0023..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-absent-or-unknown-procedure.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-event-status.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-event-status.json deleted file mode 100644 index aaad08b83e8..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-event-status.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid-slice.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid-slice.json deleted file mode 100644 index 4dcb4791944..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid-slice.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid.json deleted file mode 100644 index fac3785fe2d..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-invalid.json +++ /dev/null @@ -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'" - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-valid.json b/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-valid.json deleted file mode 100644 index 4554379edad..00000000000 --- a/hapi-fhir-jpaserver-test-r4/src/test/resources/validation/procedure/validateCode-ValueSet-procedure-code-valid.json +++ /dev/null @@ -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" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProviders.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProviders.java deleted file mode 100644 index a3c55c04439..00000000000 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProviders.java +++ /dev/null @@ -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); -

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 implements IMyValidationProvider { - private final Map myExceptionMap = new HashMap<>(); - private boolean myShouldThrowExceptionForResourceNotFound = true; - private final Map myTerminologyResponseMap = new HashMap<>(); - private final Map 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 getParameterType(); - - @Override - public

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 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); - } -} diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersDstu3.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersDstu3.java deleted file mode 100644 index 95c01392212..00000000000 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersDstu3.java +++ /dev/null @@ -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 { - @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 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 getResourceType() { - return CodeSystem.class; - } - @Override - Class 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 { - @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 getResourceType() { - return ValueSet.class; - } - @Override - Class 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; - } - } -} diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java index 7a05e197ae6..1b12e20ec62 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java @@ -190,7 +190,7 @@ public class CommonCodeSystemsTerminologyService implements IValidationSupport { return new CodeValidationResult() .setSeverity(IssueSeverity.ERROR) .setMessage(theMessage) - .setIssues(Collections.singletonList(new CodeValidationIssue( + .setCodeValidationIssues(Collections.singletonList(new CodeValidationIssue( theMessage, IssueSeverity.ERROR, CodeValidationIssueCode.INVALID, diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java index a617e04c41b..67e553e3d3b 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java @@ -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.CodeSystem; import org.hl7.fhir.r5.model.Enumerations; +import org.hl7.fhir.utilities.validation.ValidationMessage; import java.util.ArrayList; import java.util.Collections; @@ -257,7 +258,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu theValidationSupportContext, theValueSet, theCodeSystemUrlAndVersion, theCode); } catch (ExpansionCouldNotBeCompletedInternallyException e) { CodeValidationResult codeValidationResult = new CodeValidationResult(); - codeValidationResult.setSeverity(IssueSeverity.ERROR); + codeValidationResult.setSeverityCode("error"); String msg = "Failed to expand ValueSet '" + vsUrl + "' (in-memory). Could not validate code " + theCodeSystemUrlAndVersion + "#" + theCode; @@ -266,7 +267,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu } codeValidationResult.setMessage(msg); - codeValidationResult.addIssue(e.getCodeValidationIssue()); + codeValidationResult.addCodeValidationIssue(e.getCodeValidationIssue()); return codeValidationResult; } @@ -550,18 +551,18 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu if (valueSetResult != null) { codeValidationResult = valueSetResult; } else { - IValidationSupport.IssueSeverity severity; + ValidationMessage.IssueSeverity severity; String message; CodeValidationIssueCode issueCode = CodeValidationIssueCode.CODE_INVALID; CodeValidationIssueCoding issueCoding = CodeValidationIssueCoding.INVALID_CODE; if ("fragment".equals(codeSystemResourceContentMode)) { - severity = IValidationSupport.IssueSeverity.WARNING; + severity = ValidationMessage.IssueSeverity.WARNING; message = "Unknown code in fragment CodeSystem '" + getFormattedCodeSystemAndCodeForMessage( theCodeSystemUrlAndVersionToValidate, theCodeToValidate) + "'"; } else { - severity = IValidationSupport.IssueSeverity.ERROR; + severity = ValidationMessage.IssueSeverity.ERROR; message = "Unknown code '" + getFormattedCodeSystemAndCodeForMessage( theCodeSystemUrlAndVersionToValidate, theCodeToValidate) @@ -573,9 +574,10 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu } codeValidationResult = new CodeValidationResult() - .setSeverity(severity) + .setSeverityCode(severity.toCode()) .setMessage(message) - .addIssue(new CodeValidationIssue(message, severity, issueCode, issueCoding)); + .addCodeValidationIssue(new CodeValidationIssue( + message, getIssueSeverityFromCodeValidationIssue(severity), issueCode, issueCoding)); } return codeValidationResult; @@ -587,6 +589,19 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu + 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( String theCodeToValidate, String theDisplayToValidate, @@ -1108,8 +1123,8 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu new CodeValidationIssue( theMessage, IssueSeverity.ERROR, - CodeValidationIssueCode.INVALID, - CodeValidationIssueCoding.VS_INVALID)); + CodeValidationIssueCode.OTHER, + CodeValidationIssueCoding.OTHER)); } for (org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent next : subExpansion.getExpansion().getContains()) { @@ -1361,7 +1376,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu .setCodeSystemVersion(theCodeSystemVersion) .setDisplay(theExpectedDisplay); if (issueSeverity != null) { - codeValidationResult.setIssues(Collections.singletonList(new CodeValidationIssue( + codeValidationResult.setCodeValidationIssues(Collections.singletonList(new CodeValidationIssue( message, theIssueSeverityForCodeDisplayMismatch, CodeValidationIssueCode.INVALID, diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java index 398eacc52a2..370f8b423dd 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java @@ -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.CodeSystem; 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.OperationOutcome; import org.hl7.fhir.r4.model.Parameters; @@ -632,7 +631,7 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup return new CodeValidationResult() .setSeverity(severity) .setMessage(theMessage) - .addIssue(new CodeValidationIssue( + .addCodeValidationIssue(new CodeValidationIssue( theMessage, severity, theIssueCode, CodeValidationIssueCoding.INVALID_CODE)); } @@ -681,13 +680,13 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup createCodeValidationIssues( (IBaseOperationOutcome) issuesValue.get(), fhirContext.getVersion().getVersion()) - .ifPresent(i -> i.forEach(result::addIssue)); + .ifPresent(i -> i.forEach(result::addCodeValidationIssue)); } else { // create a validation issue out of the message // this is a workaround to overcome an issue in the FHIR Validator library // where ValueSet bindings are only reading issues but not messages // @see https://github.com/hapifhir/org.hl7.fhir.core/issues/1766 - result.addIssue(createCodeValidationIssue(result.getMessage())); + result.addCodeValidationIssue(createCodeValidationIssue(result.getMessage())); } return result; } @@ -718,42 +717,23 @@ public class RemoteTerminologyServiceValidationSupport extends BaseValidationSup private static Collection createCodeValidationIssuesR4(OperationOutcome theOperationOutcome) { return theOperationOutcome.getIssue().stream() - .map(issueComponent -> { - String diagnostics = issueComponent.getDiagnostics(); - 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; - }) + .map(issueComponent -> + createCodeValidationIssue(issueComponent.getDetails().getText())) .collect(Collectors.toList()); } private static Collection createCodeValidationIssuesDstu3( org.hl7.fhir.dstu3.model.OperationOutcome theOperationOutcome) { return theOperationOutcome.getIssue().stream() - .map(issueComponent -> { - String diagnostics = issueComponent.getDiagnostics(); - 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; - }) + .map(issueComponent -> + createCodeValidationIssue(issueComponent.getDetails().getText())) .collect(Collectors.toList()); } private static CodeValidationIssue createCodeValidationIssue(String theMessage) { return new CodeValidationIssue( theMessage, + // assume issue type is OperationOutcome.IssueType#CODEINVALID as it is the only match IssueSeverity.ERROR, CodeValidationIssueCode.INVALID, CodeValidationIssueCoding.INVALID_CODE); diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java index 265debed058..1898292c451 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java @@ -87,7 +87,7 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup result.setSeverity(null); result.setMessage(null); } else { - result.addIssue(new CodeValidationIssue( + result.addCodeValidationIssue(new CodeValidationIssue( theMessage, myNonExistentCodeSystemSeverity, CodeValidationIssueCode.NOT_FOUND, diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportUtils.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportUtils.java index 7093ab2a7ff..7321f33d8c8 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportUtils.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportUtils.java @@ -11,17 +11,6 @@ public final class 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) { if (theValueSet instanceof org.hl7.fhir.dstu3.model.ValueSet) { return extractCodeSystemForCodeDSTU3((org.hl7.fhir.dstu3.model.ValueSet) theValueSet, theCode); diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapper.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapper.java index 393d8ce1dc5..f0f3f41e7f9 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapper.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapper.java @@ -62,7 +62,6 @@ import java.util.Map; import java.util.Objects; 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.toSet; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -297,7 +296,7 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo theResult.getCodeSystemVersion(), conceptDefinitionComponent, display, - getIssuesForCodeValidation(theResult.getIssues())); + getIssuesForCodeValidation(theResult.getCodeValidationIssues())); } if (retVal == null) { @@ -308,36 +307,73 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo } private List getIssuesForCodeValidation( - List theIssues) { - List issueComponents = new ArrayList<>(); + List codeValidationIssues) { + List issues = new ArrayList<>(); - for (IValidationSupport.CodeValidationIssue issue : theIssues) { - OperationOutcome.IssueSeverity severity = - OperationOutcome.IssueSeverity.fromCode(issue.getSeverity().getCode()); - OperationOutcome.IssueType issueType = - OperationOutcome.IssueType.fromCode(issue.getType().getCode()); - String diagnostics = issue.getDiagnostics(); + for (IValidationSupport.CodeValidationIssue codeValidationIssue : codeValidationIssues) { - IValidationSupport.CodeValidationIssueDetails details = issue.getDetails(); - CodeableConcept codeableConcept = new CodeableConcept().setText(details.getText()); - details.getCodings().forEach(detailCoding -> codeableConcept - .addCoding() - .setSystem(detailCoding.getSystem()) - .setCode(detailCoding.getCode())); + CodeableConcept codeableConcept = new CodeableConcept().setText(codeValidationIssue.getMessage()); + codeableConcept.addCoding( + "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", + getIssueCodingFromCodeValidationIssue(codeValidationIssue), + null); - OperationOutcome.OperationOutcomeIssueComponent issueComponent = + OperationOutcome.OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent() - .setSeverity(severity) - .setCode(issueType) - .setDetails(codeableConcept) - .setDiagnostics(diagnostics); - issueComponent - .addExtension() + .setSeverity(getIssueSeverityFromCodeValidationIssue(codeValidationIssue)) + .setCode(getIssueTypeFromCodeValidationIssue(codeValidationIssue)) + .setDetails(codeableConcept); + issue.getDetails().setText(codeValidationIssue.getMessage()); + issue.addExtension() .setUrl("http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id") .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 @@ -815,22 +851,25 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo .getRootValidationSupport() .validateCodeInValueSet( 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 might also be invalid in the code system, so we will check that as well and add those issues to our result. */ IValidationSupport.CodeValidationResult codeSystemResult = validateCodeInCodeSystem(theValidationOptions, theSystem, theCode, theDisplay); - final boolean valueSetResultContainsInvalidDisplay = result.getIssues().stream() - .anyMatch(VersionSpecificWorkerContextWrapper::hasInvalidDisplayDetailCode); + final boolean valueSetResultContainsInvalidDisplay = result.getCodeValidationIssues().stream() + .anyMatch(codeValidationIssue -> codeValidationIssue.getCoding() + == IValidationSupport.CodeValidationIssueCoding.INVALID_DISPLAY); 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 issues from code system validation, they will only repeat what was already caught. */ - if (!hasInvalidDisplayDetailCode(codeValidationIssue) || !valueSetResultContainsInvalidDisplay) { - result.addIssue(codeValidationIssue); + if (codeValidationIssue.getCoding() != IValidationSupport.CodeValidationIssueCoding.INVALID_DISPLAY + || !valueSetResultContainsInvalidDisplay) { + result.addCodeValidationIssue(codeValidationIssue); } } } @@ -838,10 +877,6 @@ public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWo return result; } - private static boolean hasInvalidDisplayDetailCode(IValidationSupport.CodeValidationIssue theIssue) { - return theIssue.hasIssueDetailCode(INVALID_DISPLAY.getCode()); - } - private IValidationSupport.CodeValidationResult validateCodeInCodeSystem( ConceptValidationOptions theValidationOptions, String theSystem, String theCode, String theDisplay) { return myValidationSupportContext diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/ILookupCodeTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/ILookupCodeTest.java index eac448ad0eb..bb7eaf1c17b 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/ILookupCodeTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/ILookupCodeTest.java @@ -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.LookupCodeRequest; 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.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 java.util.stream.IntStream.range; import static org.assertj.core.api.Assertions.assertThat; -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_NAME; -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.LANGUAGE; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_NAME; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_VERSION; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.DISPLAY; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.LANGUAGE; 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.assertFalse; @@ -190,6 +189,8 @@ public interface ILookupCodeTest { // verify assertNotNull(outcome); + assertEquals(theRequest.getCode(), getLookupCodeProvider().getCode()); + assertEquals(theRequest.getSystem(), getLookupCodeProvider().getSystem()); assertEquals(theExpectedResult.isFound(), outcome.isFound()); assertEquals(theExpectedResult.getErrorMessage(), outcome.getErrorMessage()); assertEquals(theExpectedResult.getCodeSystemDisplayName(), outcome.getCodeSystemDisplayName()); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyLookupCodeTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyLookupCodeTest.java index 95c4fd7d3b9..5ba79bd3e6f 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyLookupCodeTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyLookupCodeTest.java @@ -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.LookupCodeRequest; -import ca.uhn.fhir.test.utilities.validation.IValidationProviders; import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyValidateCodeTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyValidateCodeTest.java index 21c5d0dc5e7..cb6bb02ac07 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyValidateCodeTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IRemoteTerminologyValidateCodeTest.java @@ -1,76 +1,17 @@ package org.hl7.fhir.common.hapi.validation; -import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.support.IValidationSupport; import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; -import org.junit.jupiter.api.Test; import java.util.Collection; import java.util.List; 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 { default List getCodeValidationIssues(IBaseOperationOutcome theOperationOutcome) { // this method should be removed once support for issues is fully implemented across all validator types Optional> issues = RemoteTerminologyServiceValidationSupport.createCodeValidationIssues(theOperationOutcome, getService().getFhirContext().getVersion().getVersion()); 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> 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> 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> 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."); - } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidateCodeTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidateCodeTest.java index 53411b440fe..52dbf1177a8 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidateCodeTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidateCodeTest.java @@ -4,9 +4,6 @@ import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 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.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -19,13 +16,12 @@ import java.util.List; import java.util.stream.Stream; import static ca.uhn.fhir.context.support.IValidationSupport.IssueSeverity.ERROR; -import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_VALIDATE_CODE; -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.hl7.fhir.common.hapi.validation.IValidationProviders.CODE; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.CODE_SYSTEM_VERSION; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.DISPLAY; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.ERROR_MESSAGE; +import static org.hl7.fhir.common.hapi.validation.IValidationProviders.VALUE_SET_URL; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -35,35 +31,21 @@ import static org.junit.jupiter.api.Assertions.fail; public interface IValidateCodeTest { - IValidationProviders.IMyValidationProvider getCodeSystemProvider(); - IValidationProviders.IMyValidationProvider getValueSetProvider(); + IValidationProviders.IMyCodeSystemProvider getCodeSystemProvider(); + IValidationProviders.IMyValueSetProvider getValueSetProvider(); IValidationSupport getService(); IBaseParameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource); String getCodeSystemError(); String getValueSetError(); IBaseOperationOutcome getCodeSystemInvalidCodeOutcome(); IBaseOperationOutcome getValueSetInvalidCodeOutcome(); - IBaseOperationOutcome getValueSetCustomDetailCodeOutcome(); - - default IBaseOperationOutcome getCodeSystemInvalidCodeOutcome(Class theResourceClass) { - return getOutcome(theResourceClass, "/terminology/OperationOutcome-CodeSystem-invalid-code.json"); - } - default IBaseOperationOutcome getValueSetInvalidCodeOutcome(Class theResourceClass) { - return getOutcome(theResourceClass, "/terminology/OperationOutcome-ValueSet-invalid-code.json"); - } - default IBaseOperationOutcome getValueSetCustomDetailCodeOutcome(Class theResourceClass) { - return getOutcome(theResourceClass, "/terminology/OperationOutcome-ValueSet-custom-issue-detail.json"); - } - default IBaseOperationOutcome getOutcome(Class theResourceClass, String theFile) { - return ClasspathUtil.loadResource(getService().getFhirContext(), theResourceClass, theFile); - } 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) { - getValueSetProvider().addTerminologyResponse(OPERATION_VALIDATE_CODE, VALUE_SET_URL, CODE, createParameters(theResult, theDisplay, theMessage, theIssuesResource)); + getValueSetProvider().setReturnParams(createParameters(theResult, theDisplay, theMessage, theIssuesResource)); } @Test @@ -109,8 +91,8 @@ public interface IValidateCodeTest { String theValidationMessage, String theCodeSystem, String theValueSetUrl) { - getCodeSystemProvider().addException(OPERATION_VALIDATE_CODE, theCodeSystem, CODE, theException); - getValueSetProvider().addException(OPERATION_VALIDATE_CODE, theValueSetUrl, CODE, theException); + getCodeSystemProvider().setException(theException); + getValueSetProvider().setException(theException); CodeValidationResult outcome = getService().validateCode(null, null, theCodeSystem, CODE, DISPLAY, theValueSetUrl); verifyErrorResultFromException(outcome, theValidationMessage, theServerMessage); @@ -123,7 +105,7 @@ public interface IValidateCodeTest { for (String message : theMessages) { assertTrue(outcome.getMessage().contains(message)); } - assertFalse(outcome.getIssues().isEmpty()); + assertFalse(outcome.getCodeValidationIssues().isEmpty()); } @Test @@ -148,7 +130,11 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertNull(outcome.getSeverity()); 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 @@ -161,7 +147,9 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertNull(outcome.getSeverity()); assertNull(outcome.getMessage()); - assertTrue(outcome.getIssues().isEmpty()); + assertTrue(outcome.getCodeValidationIssues().isEmpty()); + + assertEquals(CODE, getCodeSystemProvider().getCode()); } @Test @@ -177,7 +165,10 @@ public interface IValidateCodeTest { assertNull(outcome.getDisplay()); assertNull(outcome.getSeverity()); assertNull(outcome.getMessage()); - assertTrue(outcome.getIssues().isEmpty()); + assertTrue(outcome.getCodeValidationIssues().isEmpty()); + + assertEquals(CODE, getCodeSystemProvider().getCode()); + assertEquals(CODE_SYSTEM, getCodeSystemProvider().getSystem()); } @Test @@ -193,11 +184,15 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertNull(outcome.getSeverity()); 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 - default void validateCode_withCodeSystemErrorWithDiagnosticsWithIssues_returnsCorrectly() { + default void validateCode_withCodeSystemError_returnsCorrectly() { IBaseOperationOutcome invalidCodeOutcome = getCodeSystemInvalidCodeOutcome(); createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, invalidCodeOutcome); @@ -209,12 +204,12 @@ public interface IValidateCodeTest { // assertEquals(CODE, outcome.getCode()); assertEquals(ERROR, outcome.getSeverity()); assertEquals(getCodeSystemError(), outcome.getMessage()); - assertFalse(outcome.getIssues().isEmpty()); + assertFalse(outcome.getCodeValidationIssues().isEmpty()); verifyIssues(invalidCodeOutcome, outcome); } @Test - default void validateCode_withCodeSystemErrorWithDiagnosticsWithoutIssues_returnsCorrectly() { + default void validateCode_withCodeSystemErrorAndIssues_returnsCorrectly() { createCodeSystemReturnParameters(false, null, ERROR_MESSAGE, null); CodeValidationResult outcome = getService() @@ -228,32 +223,10 @@ public interface IValidateCodeTest { assertNull(outcome.getDisplay()); assertEquals(ERROR, outcome.getSeverity()); assertEquals(expectedError, outcome.getMessage()); - assertFalse(outcome.getIssues().isEmpty()); - assertEquals(1, outcome.getIssues().size()); - assertEquals(expectedError, outcome.getIssues().get(0).getDiagnostics()); - assertEquals(ERROR, outcome.getIssues().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()); + assertFalse(outcome.getCodeValidationIssues().isEmpty()); + assertEquals(1, outcome.getCodeValidationIssues().size()); + assertEquals(expectedError, outcome.getCodeValidationIssues().get(0).getMessage()); + assertEquals(ERROR, outcome.getCodeValidationIssues().get(0).getSeverity()); } @Test @@ -269,7 +242,10 @@ public interface IValidateCodeTest { assertNull(outcome.getDisplay()); assertNull(outcome.getSeverity()); assertNull(outcome.getMessage()); - assertTrue(outcome.getIssues().isEmpty()); + assertTrue(outcome.getCodeValidationIssues().isEmpty()); + + assertEquals(CODE, getValueSetProvider().getCode()); + assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet()); } @Test @@ -285,7 +261,11 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertNull(outcome.getSeverity()); 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 @@ -303,9 +283,13 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertEquals(ERROR, outcome.getSeverity()); assertEquals(expectedError, outcome.getMessage()); - assertEquals(1, outcome.getIssues().size()); - assertEquals(expectedError, outcome.getIssues().get(0).getDiagnostics()); - assertEquals(ERROR, outcome.getIssues().get(0).getSeverity()); + assertEquals(1, outcome.getCodeValidationIssues().size()); + assertEquals(expectedError, outcome.getCodeValidationIssues().get(0).getMessage()); + assertEquals(ERROR, outcome.getCodeValidationIssues().get(0).getSeverity()); + + assertEquals(CODE, getValueSetProvider().getCode()); + assertEquals(DISPLAY, getValueSetProvider().getDisplay()); + assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet()); } @Test @@ -322,28 +306,24 @@ public interface IValidateCodeTest { assertEquals(DISPLAY, outcome.getDisplay()); assertEquals(ERROR, outcome.getSeverity()); assertEquals(getValueSetError(), outcome.getMessage()); - assertFalse(outcome.getIssues().isEmpty()); + assertFalse(outcome.getCodeValidationIssues().isEmpty()); verifyIssues(invalidCodeOutcome, outcome); + + assertEquals(CODE, getValueSetProvider().getCode()); + assertEquals(DISPLAY, getValueSetProvider().getDisplay()); + assertEquals(VALUE_SET_URL, getValueSetProvider().getValueSet()); } default void verifyIssues(IBaseOperationOutcome theOperationOutcome, CodeValidationResult theResult) { List issues = getCodeValidationIssues(theOperationOutcome); - assertEquals(issues.size(), theResult.getIssues().size()); + assertEquals(issues.size(), theResult.getCodeValidationIssues().size()); for (int i = 0; i < issues.size(); i++) { IValidationSupport.CodeValidationIssue expectedIssue = issues.get(i); - IValidationSupport.CodeValidationIssue actualIssue = theResult.getIssues().get(i); - assertEquals(expectedIssue.getType().getCode(), actualIssue.getType().getCode()); + IValidationSupport.CodeValidationIssue actualIssue = theResult.getCodeValidationIssues().get(i); + assertEquals(expectedIssue.getCode(), actualIssue.getCode()); assertEquals(expectedIssue.getSeverity(), actualIssue.getSeverity()); - assertEquals(expectedIssue.getDetails().getText(), actualIssue.getDetails().getText()); - assertEquals(expectedIssue.getDetails().getCodings().size(), actualIssue.getDetails().getCodings().size()); - 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()); + assertEquals(expectedIssue.getCoding(), actualIssue.getCoding()); + assertEquals(expectedIssue.getMessage(), actualIssue.getMessage()); } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidationProviders.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidationProviders.java new file mode 100644 index 00000000000..1537f8e5c00 --- /dev/null +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/IValidationProviders.java @@ -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); + } +} diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapperTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapperTest.java index cbc79fadc98..57aae8d96f9 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapperTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/validator/VersionSpecificWorkerContextWrapperTest.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks; import ca.uhn.fhir.i18n.HapiLocalizer; import ca.uhn.hapi.converters.canonical.VersionCanonicalizer; + import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; 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.mockito.quality.Strictness; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import java.util.List; + public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestWithInlineMocks { final byte[] EXPECTED_BINARY_CONTENT_1 = "dummyBinaryContent1".getBytes(); @@ -80,7 +80,7 @@ public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestW } @Test - public void validateCode_codeInValueSet_resolvesCodeSystemFromValueSet() { + public void validateCode_normally_resolvesCodeSystemFromValueSet() { // setup IValidationSupport validationSupport = mockValidationSupport(); ValidationSupportContext mockContext = mockValidationSupportContext(validationSupport); @@ -90,7 +90,8 @@ public class VersionSpecificWorkerContextWrapperTest extends BaseValidationTestW 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"); - 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 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()); } - @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 public void isPrimitive_primitive() { // setup diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2/hapi/validation/FhirInstanceValidatorDstu2Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2/hapi/validation/FhirInstanceValidatorDstu2Test.java index 5a53ba0ac3d..da73c0be800 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2/hapi/validation/FhirInstanceValidatorDstu2Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2/hapi/validation/FhirInstanceValidatorDstu2Test.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.support.ConceptValidationOptions; import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.fhirpath.BaseValidationTestWithInlineMocks; import ca.uhn.fhir.model.dstu2.composite.PeriodDt; 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.QuestionnaireResponseStatus; 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.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -37,7 +41,9 @@ import org.mockito.stubbing.Answer; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -94,7 +100,7 @@ public class FhirInstanceValidatorDstu2Test extends BaseValidationTestWithInline if (myValidConcepts.contains(system + "___" + code)) { retVal = new IValidationSupport.CodeValidationResult().setCode(code); } 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 { retVal = null; } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java index a8c44097e26..d04e90d2d7a 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java @@ -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.IValidatorResourceFetcher; 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.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -228,10 +229,10 @@ public class FhirInstanceValidatorDstu3Test extends BaseValidationTestWithInline retVal = new IValidationSupport.CodeValidationResult().setCode(code); } else if (myValidSystems.contains(system)) { 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)) { 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)) { CodeSystem cs = myCodeSystems.get(system); Optional found = cs.getConcept().stream().filter(t -> t.getCode().equals(code)).findFirst(); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/IValidateCodeProvidersDstu3.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/IValidateCodeProvidersDstu3.java new file mode 100644 index 00000000000..0c639e310ee --- /dev/null +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/IValidateCodeProvidersDstu3.java @@ -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 thePropertyNames, + RequestDetails theRequestDetails + ) { + myCode = theCode; + return myReturnParams; + } + + @Override + public Class 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 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; + } + } +} diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java index 57591b31e76..7804b9df10f 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java @@ -41,6 +41,7 @@ import org.hl7.fhir.dstu3.model.Type; import org.hl7.fhir.dstu3.model.UriType; import org.hl7.fhir.dstu3.model.ValueSet; 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.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -55,8 +56,6 @@ import java.util.Date; import java.util.List; 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.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.BOOLEAN; 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))) .thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0")); 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.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))) .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))) - .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; @@ -1035,7 +1034,7 @@ public class QuestionnaireResponseValidatorDstu3Test { when(myValSupport.validateCode(any(), any(), eq("http://codesystems.com/system"), eq("code0"), any(), nullable(String.class))) .thenReturn(new IValidationSupport.CodeValidationResult().setCode("code0")); 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.setContent(CodeSystemContentMode.COMPLETE); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeDstu3Test.java index 56bc892c3d4..6e98c4b31a9 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeDstu3Test.java @@ -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.ResourceNotFoundException; import ca.uhn.fhir.test.utilities.server.RestfulServerExtension; -import ca.uhn.fhir.test.utilities.validation.IValidationProviders; import jakarta.servlet.http.HttpServletRequest; 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.dstu3.model.BooleanType; import org.hl7.fhir.dstu3.model.CodeSystem; @@ -164,6 +164,8 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL @SuppressWarnings("unused") static class MyLookupCodeProviderDstu3 implements IValidationProviders.IMyLookupCodeProvider { + private UriType mySystemUrl; + private CodeType myCode; private LookupCodeResult myLookupCodeResult; @Override @@ -188,6 +190,8 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL @OperationParam(name= " property", max = OperationParam.MAX_UNLIMITED) List thePropertyNames, RequestDetails theRequestDetails ) { + myCode = theCode; + mySystemUrl = theSystem; if (theSystem == null) { throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode)); } @@ -201,5 +205,15 @@ public class RemoteTerminologyLookupCodeDstu3Test implements IRemoteTerminologyL public Class getResourceType() { return CodeSystem.class; } + + @Override + public String getCode() { + return myCode != null ? myCode.getValueAsString() : null; + } + + @Override + public String getSystem() { + return mySystemUrl != null ? mySystemUrl.getValueAsString() : null; + } } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeWithResponseFileDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeWithResponseFileDstu3Test.java index 4817542ef4d..48a99f260d0 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeWithResponseFileDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyLookupCodeWithResponseFileDstu3Test.java @@ -5,10 +5,13 @@ import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.LookupCodeRequest; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; 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.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.StringType; 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.BeforeEach; import org.junit.jupiter.api.Test; @@ -16,15 +19,13 @@ import org.junit.jupiter.api.extension.RegisterExtension; 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.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test { private static final FhirContext ourCtx = FhirContext.forDstu3Cached(); - private IValidationProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider; + private IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider; @RegisterExtension public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx); @@ -35,7 +36,7 @@ public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test { String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl); mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true)); - myCodeSystemProvider = new IValidationProvidersDstu3.MyCodeSystemProviderDstu3(); + myCodeSystemProvider = new IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3(); ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider); } @@ -46,10 +47,13 @@ public class RemoteTerminologyLookupCodeWithResponseFileDstu3Test { } @Test void lookupCode_withParametersOutput_convertsCorrectly() { - String outputFile ="/terminology/CodeSystem-lookup-output-with-subproperties.json"; - IBaseParameters resultParameters = myCodeSystemProvider.addTerminologyResponse(OPERATION_LOOKUP, CODE_SYSTEM, CODE, ourCtx, outputFile); + String paramsAsString = ClasspathUtil.loadResource("/terminology/CodeSystem-lookup-output-with-subproperties.json"); + 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 IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyValidateCodeDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyValidateCodeDstu3Test.java index 2f573ad3e5f..af4f39f0926 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyValidateCodeDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/RemoteTerminologyValidateCodeDstu3Test.java @@ -4,18 +4,16 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.test.utilities.server.RestfulServerExtension; -import ca.uhn.fhir.test.utilities.validation.IValidationProviders; -import ca.uhn.fhir.test.utilities.validation.IValidationProvidersDstu3; +import ca.uhn.fhir.util.ClasspathUtil; 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.dstu3.model.BooleanType; -import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.OperationOutcome; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.Resource; 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.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.jupiter.api.AfterEach; @@ -24,11 +22,6 @@ import org.junit.jupiter.api.extension.RegisterExtension; 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_VALUE_SET; @@ -45,8 +38,8 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog private static final FhirContext ourCtx = FhirContext.forDstu3Cached(); @RegisterExtension public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx); - private IValidationProviders.MyValidationProvider myCodeSystemProvider; - private IValidationProviders.MyValidationProvider myValueSetProvider; + private IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 myCodeSystemProvider; + private IValidateCodeProvidersDstu3.MyValueSetProviderDstu3 myValueSetProvider; private RemoteTerminologyServiceValidationSupport mySvc; private String myCodeSystemError, myValueSetError; @@ -55,14 +48,14 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); myCodeSystemError = ourCtx.getLocalizer().getMessage( 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( 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.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true)); - myCodeSystemProvider = new IValidationProvidersDstu3.MyCodeSystemProviderDstu3(); - myValueSetProvider = new IValidationProvidersDstu3.MyValueSetProviderDstu3(); + myCodeSystemProvider = new IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3(); + myValueSetProvider = new IValidateCodeProvidersDstu3.MyValueSetProviderDstu3(); ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider); } @@ -89,40 +82,45 @@ public class RemoteTerminologyValidateCodeDstu3Test implements IRemoteTerminolog } @Override - public IValidationProviders.IMyValidationProvider getCodeSystemProvider() { + public IValidateCodeProvidersDstu3.MyCodeSystemProviderDstu3 getCodeSystemProvider() { return myCodeSystemProvider; } @Override - public IValidationProviders.IMyValidationProvider getValueSetProvider() { + public IValidateCodeProvidersDstu3.MyValueSetProviderDstu3 getValueSetProvider() { return myValueSetProvider; } @Override public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() { - return getCodeSystemInvalidCodeOutcome(OperationOutcome.class); + return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-CodeSystem-invalid-code.json"); } @Override public IBaseOperationOutcome getValueSetInvalidCodeOutcome() { - return getValueSetInvalidCodeOutcome(OperationOutcome.class); - } - - @Override - public IBaseOperationOutcome getValueSetCustomDetailCodeOutcome() { - return getValueSetCustomDetailCodeOutcome(OperationOutcome.class); + return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-ValueSet-invalid-code.json"); } @Override public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) { Parameters parameters = new Parameters(); parameters.addParameter().setName("result").setValue(new BooleanType(theResult)); - parameters.addParameter().setName("code").setValue(new StringType(CODE)); - parameters.addParameter().setName("system").setValue(new UriType(CODE_SYSTEM)); - parameters.addParameter().setName("version").setValue(new StringType(CODE_SYSTEM_VERSION)); + parameters.addParameter().setName("code").setValue(new StringType(IValidationProviders.CODE)); + parameters.addParameter().setName("system").setValue(new UriType(IValidationProviders.CODE_SYSTEM)); + parameters.addParameter().setName("version").setValue(new StringType(IValidationProviders.CODE_SYSTEM_VERSION)); parameters.addParameter().setName("display").setValue(new StringType(theDisplay)); parameters.addParameter().setName("message").setValue(new StringType(theMessage)); parameters.addParameter().setName("issues").setResource((Resource) theIssuesResource); 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)); + } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java index fb46f7f8008..d03c3aa974d 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java @@ -307,10 +307,10 @@ public class FhirInstanceValidatorR4Test extends BaseValidationTestWithInlineMoc retVal = new IValidationSupport.CodeValidationResult().setCode(code); } else if (myValidSystems.contains(system)) { 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)) { 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 { retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl); } diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersR4.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/IValidateCodeProvidersR4.java similarity index 55% rename from hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersR4.java rename to hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/IValidateCodeProvidersR4.java index 504fd90d700..fd03a8163ff 100644 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersR4.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/IValidateCodeProvidersR4.java @@ -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.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.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.BooleanType; @@ -19,29 +21,38 @@ import org.hl7.fhir.r4.model.ValueSet; import java.util.List; -public interface IValidationProvidersR4 { +public interface IValidateCodeProvidersR4 { @SuppressWarnings("unused") - class MyCodeSystemProviderR4 extends IValidationProviders.MyValidationProvider { + 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 = "message", type = StringType.class), @OperationParam(name = "display", type = StringType.class) }) - public IBaseParameters validateCode( + 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 ) throws Exception { - String url = theCodeSystemUrl != null ? theCodeSystemUrl.getValue() : null; - String code = theCode != null ? theCode.getValue() : null; - return getTerminologyResponse("$validate-code", url, code); + mySystemUrl = theCodeSystemUrl; + myCode = theCode; + 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 = "version", type = StringType.class), @OperationParam(name = "display", type = StringType.class, min = 1), @@ -58,39 +69,54 @@ public interface IValidationProvidersR4 { @OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List thePropertyNames, RequestDetails theRequestDetails ) throws Exception { - String url = theSystem != null ? theSystem.getValue() : null; - String code = theCode != null ? theCode.getValue() : null; - return getTerminologyResponse("$lookup", url, code); + mySystemUrl = theSystem; + myCode = theCode; + if (myException != null) { + throw myException; + } + return myReturnParams; } + @Override public Class getResourceType() { return CodeSystem.class; } - @Override - Class getParameterType() { - return Parameters.class; + public void setException(Exception theException) { + myException = theException; } - @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; + 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 MyValueSetProviderR4 extends IValidationProviders.MyValidationProvider { + 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 = "message", type = StringType.class), @OperationParam(name = "display", type = StringType.class) }) - public IBaseParameters validateCode( + public Parameters validateCode( HttpServletRequest theServletRequest, @IdParam(optional = true) IdType theId, @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 = "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); + mySystemUrl = theSystem; + myValueSetUrl = theValueSetUrl; + myCode = theCode; + myDisplay = theDisplay; + if (myException != null) { + throw myException; + } + return myReturnParams; } + @Override public Class getResourceType() { return ValueSet.class; } - @Override - Class getParameterType() { - return Parameters.class; + public void setException(Exception theException) { + myException = theException; } @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; + 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; } } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeR4Test.java index 382f621f547..d67966df6d4 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeR4Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeR4Test.java @@ -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.ResourceNotFoundException; 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 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.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseParameters; @@ -53,7 +52,7 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook @RegisterExtension public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx); private final RemoteTerminologyServiceValidationSupport mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx); - private IValidationProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider; + private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider; private MyLookupCodeProviderR4 myLookupCodeProviderR4; @BeforeEach @@ -61,7 +60,7 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); mySvc.setBaseUrl(baseUrl); mySvc.addClientInterceptor(new LoggingInterceptor(true)); - myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4(); + myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4(); myLookupCodeProviderR4 = new MyLookupCodeProviderR4(); ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myLookupCodeProviderR4); } @@ -167,6 +166,8 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook @SuppressWarnings("unused") static class MyLookupCodeProviderR4 implements IValidationProviders.IMyLookupCodeProvider { + private UriType mySystemUrl; + private CodeType myCode; private LookupCodeResult myLookupCodeResult; @Override @@ -191,6 +192,8 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook @OperationParam(name = "property", max = OperationParam.MAX_UNLIMITED) List thePropertyNames, RequestDetails theRequestDetails ) { + myCode = theCode; + mySystemUrl = theSystem; if (theSystem == null) { throw new InvalidRequestException(MessageFormat.format(MESSAGE_RESPONSE_INVALID, theCode)); } @@ -203,5 +206,15 @@ public class RemoteTerminologyLookupCodeR4Test implements IRemoteTerminologyLook public Class getResourceType() { return CodeSystem.class; } + + @Override + public String getCode() { + return myCode != null ? myCode.getValueAsString() : null; + } + + @Override + public String getSystem() { + return mySystemUrl != null ? mySystemUrl.getValueAsString() : null; + } } } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeWithResponseFileR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeWithResponseFileR4Test.java index a0896bd8c4e..37eba91d0ca 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeWithResponseFileR4Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyLookupCodeWithResponseFileR4Test.java @@ -5,9 +5,12 @@ import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.LookupCodeRequest; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; 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.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.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -16,15 +19,13 @@ import org.junit.jupiter.api.extension.RegisterExtension; 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.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class RemoteTerminologyLookupCodeWithResponseFileR4Test { private static final FhirContext ourCtx = FhirContext.forR4Cached(); - private IValidationProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider; + private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider; @RegisterExtension public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx); @@ -35,7 +36,7 @@ public class RemoteTerminologyLookupCodeWithResponseFileR4Test { String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); mySvc = new RemoteTerminologyServiceValidationSupport(ourCtx, baseUrl); mySvc.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true)); - myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4(); + myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4(); ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider); } @@ -47,10 +48,13 @@ public class RemoteTerminologyLookupCodeWithResponseFileR4Test { @Test void lookupCode_withParametersOutput_convertsCorrectly() { - String outputFile ="/terminology/CodeSystem-lookup-output-with-subproperties.json"; - IBaseParameters resultParameters = myCodeSystemProvider.addTerminologyResponse(OPERATION_LOOKUP, CODE_SYSTEM, CODE, ourCtx, outputFile); + String paramsAsString = ClasspathUtil.loadResource("/terminology/CodeSystem-lookup-output-with-subproperties.json"); + 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 IValidationSupport.LookupCodeResult outcome = mySvc.lookupCode(null, request); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyValidateCodeR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyValidateCodeR4Test.java index ffd8045a8a5..08f6c251869 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyValidateCodeR4Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/RemoteTerminologyValidateCodeR4Test.java @@ -2,8 +2,8 @@ package org.hl7.fhir.r4.validation; import ca.uhn.fhir.context.FhirContext; 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.jpa.model.util.JpaConstants; import ca.uhn.fhir.parser.IJsonLikeParser; import ca.uhn.fhir.rest.client.api.IClientInterceptor; 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.ResourceNotFoundException; 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 ca.uhn.fhir.util.ParametersUtil; import com.google.common.collect.Lists; 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.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -39,12 +39,6 @@ import java.util.Collections; import java.util.List; 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.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; @@ -67,8 +61,8 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa private static final FhirContext ourCtx = FhirContext.forR4Cached(); @RegisterExtension public static RestfulServerExtension ourRestfulServerExtension = new RestfulServerExtension(ourCtx); - private IValidationProviders.IMyValidationProvider myCodeSystemProvider; - private IValidationProviders.IMyValidationProvider myValueSetProvider; + private IValidateCodeProvidersR4.MyCodeSystemProviderR4 myCodeSystemProvider; + private IValidateCodeProvidersR4.MyValueSetProviderR4 myValueSetProvider; private RemoteTerminologyServiceValidationSupport mySvc; private String myCodeSystemError, myValueSetError; @@ -77,14 +71,14 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa String baseUrl = "http://localhost:" + ourRestfulServerExtension.getPort(); myCodeSystemError = ourCtx.getLocalizer().getMessage( 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( 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.addClientInterceptor(new LoggingInterceptor(false).setLogRequestSummary(true).setLogResponseSummary(true)); - myCodeSystemProvider = new IValidationProvidersR4.MyCodeSystemProviderR4(); - myValueSetProvider = new IValidationProvidersR4.MyValueSetProviderR4(); + myCodeSystemProvider = new IValidateCodeProvidersR4.MyCodeSystemProviderR4(); + myValueSetProvider = new IValidateCodeProvidersR4.MyValueSetProviderR4(); ourRestfulServerExtension.getRestfulServer().registerProviders(myCodeSystemProvider, myValueSetProvider); } @@ -101,12 +95,12 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa } @Override - public IValidationProviders.IMyValidationProvider getCodeSystemProvider() { + public IValidationProviders.IMyCodeSystemProvider getCodeSystemProvider() { return myCodeSystemProvider; } @Override - public IValidationProviders.IMyValidationProvider getValueSetProvider() { + public IValidationProviders.IMyValueSetProvider getValueSetProvider() { return myValueSetProvider; } @@ -122,40 +116,51 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @Override public IBaseOperationOutcome getCodeSystemInvalidCodeOutcome() { - return getCodeSystemInvalidCodeOutcome(OperationOutcome.class); + return ClasspathUtil.loadResource(getService().getFhirContext(), OperationOutcome.class, "/terminology/OperationOutcome-CodeSystem-invalid-code.json"); } @Override 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); + public List getCodeValidationIssues(IBaseOperationOutcome theOperationOutcome) { + 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 void validateCodeInValueSet_success() { - createValueSetReturnParameters(true, DISPLAY, null, null); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); 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); - assertEquals(CODE, outcome.getCode()); - assertEquals(DISPLAY, outcome.getDisplay()); + assertEquals(IValidationProviders.CODE, outcome.getCode()); + assertEquals(IValidationProviders.DISPLAY, outcome.getDisplay()); assertNull(outcome.getSeverity()); assertNull(outcome.getMessage()); + + assertEquals(IValidationProviders.CODE, myValueSetProvider.getCode()); + assertEquals(IValidationProviders.DISPLAY, myValueSetProvider.getDisplay()); + assertEquals(IValidationProviders.VALUE_SET_URL, myValueSetProvider.getValueSet()); } @Override public Parameters createParameters(Boolean theResult, String theDisplay, String theMessage, IBaseResource theIssuesResource) { Parameters parameters = new Parameters() - .addParameter("code", CODE) - .addParameter("system", CODE_SYSTEM) - .addParameter("version", CODE_SYSTEM_VERSION) + .addParameter("code", IValidationProviders.CODE) + .addParameter("system", IValidationProviders.CODE_SYSTEM) + .addParameter("version", IValidationProviders.CODE_SYSTEM_VERSION) .addParameter("display", theDisplay) .addParameter("message", theMessage); if (theResult != null) { @@ -176,16 +181,16 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @Test void validateCodeInValueSet_uniqueComposeInclude() { - createValueSetReturnParameters(true, DISPLAY, null, null); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); ValueSet valueSet = new ValueSet(); - valueSet.setUrl(VALUE_SET_URL); + valueSet.setUrl(IValidationProviders.VALUE_SET_URL); String systemUrl = "http://hl7.org/fhir/ValueSet/administrative-gender"; valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude( Collections.singletonList(new ValueSet.ConceptSetComponent().setSystem(systemUrl)) )); 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) assertNotNull(outcome); @@ -206,16 +211,16 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @ParameterizedTest @MethodSource(value = "getRemoteTerminologyServerExceptions") void validateCodeInValueSet_systemNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) { - getValueSetProvider().addException("$validate-code", VALUE_SET_URL, CODE, theException); - createValueSetReturnParameters(true, DISPLAY, null, null); + myValueSetProvider.setException(theException); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); ValueSet valueSet = new ValueSet(); - valueSet.setUrl(VALUE_SET_URL); + valueSet.setUrl(IValidationProviders.VALUE_SET_URL); valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude( Lists.newArrayList(new ValueSet.ConceptSetComponent(), new ValueSet.ConceptSetComponent()))); 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://"; verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage); @@ -225,11 +230,11 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @ParameterizedTest @MethodSource(value = "getRemoteTerminologyServerExceptions") void validateCodeInValueSet_systemPresentCodeNotPresent_returnsValidationResultWithError(Exception theException, String theServerMessage) { - getValueSetProvider().addException(JpaConstants.OPERATION_VALIDATE_CODE, VALUE_SET_URL, CODE, theException); - createValueSetReturnParameters(true, DISPLAY, null, null); + myValueSetProvider.setException(theException); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); 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 systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset"; valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude( @@ -238,7 +243,7 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa new ValueSet.ConceptSetComponent().setSystem(systemUrl2)))); 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://"; verifyErrorResultFromException(outcome, unknownCodeForValueSetError, theServerMessage); @@ -247,10 +252,10 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @Test void validateCodeInValueSet_systemPresentCodePresentValidatesOKNoVersioned() { - createValueSetReturnParameters(true, DISPLAY, null, null); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); 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 systemUrl2 = "http://hl7.org/fhir/ValueSet/other-valueset"; valueSet.setCompose(new ValueSet.ValueSetComposeComponent().setInclude( @@ -259,14 +264,14 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa new ValueSet.ConceptSetComponent().setSystem(systemUrl2).setConcept( Lists.newArrayList( new ValueSet.ConceptReferenceComponent().setCode("not-the-code"), - new ValueSet.ConceptReferenceComponent().setCode(CODE) ) + new ValueSet.ConceptReferenceComponent().setCode(IValidationProviders.CODE) ) )) )); TestClientInterceptor requestInterceptor = new TestClientInterceptor(); mySvc.addClientInterceptor(requestInterceptor); 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); assertEquals(systemUrl2, requestInterceptor.getCapturedSystemParameter()); @@ -275,10 +280,10 @@ public class RemoteTerminologyValidateCodeR4Test implements IRemoteTerminologyVa @Test void validateCodeInValueSet_systemPresentCodePresentValidatesOKVersioned() { - createValueSetReturnParameters(true, DISPLAY, null, null); + createValueSetReturnParameters(true, IValidationProviders.DISPLAY, null, null); 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 systemVersion = "3.0.2"; 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( Lists.newArrayList( new ValueSet.ConceptReferenceComponent().setCode("not-the-code"), - new ValueSet.ConceptReferenceComponent().setCode(CODE) ) + new ValueSet.ConceptReferenceComponent().setCode(IValidationProviders.CODE) ) )) )); TestClientInterceptor requestInterceptor = new TestClientInterceptor(); mySvc.addClientInterceptor(requestInterceptor); 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); assertEquals(systemUrl2 + "|" + system2Version, requestInterceptor.getCapturedSystemParameter()); diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4b/validation/FhirInstanceValidatorR4BTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4b/validation/FhirInstanceValidatorR4BTest.java index d5035a8048e..ca55a41bf4c 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4b/validation/FhirInstanceValidatorR4BTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4b/validation/FhirInstanceValidatorR4BTest.java @@ -31,7 +31,6 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4b.conformance.ProfileUtilities; 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.model.AllergyIntolerance; 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.ValueSetExpansionComponent; 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.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; @@ -203,7 +203,7 @@ public class FhirInstanceValidatorR4BTest extends BaseValidationTestWithInlineMo retVal = new IValidationSupport.CodeValidationResult().setCode(code); } else if (myValidSystems.contains(system)) { 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 { retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl); } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java index abcb0f94704..f0ea48686e1 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java @@ -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.constants.BestPracticeWarningLevel; 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.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; @@ -199,10 +200,10 @@ public class FhirInstanceValidatorR5Test extends BaseValidationTestWithInlineMoc retVal = new IValidationSupport.CodeValidationResult().setCode(code); } else if (myValidSystems.contains(system)) { 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)) { 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 { retVal = myDefaultValidationSupport.validateCode(new ValidationSupportContext(myDefaultValidationSupport), options, system, code, display, valueSetUrl); } diff --git a/hapi-fhir-validation/src/test/resources/terminology/OperationOutcome-ValueSet-custom-issue-detail.json b/hapi-fhir-validation/src/test/resources/terminology/OperationOutcome-ValueSet-custom-issue-detail.json deleted file mode 100644 index 0823a430cf8..00000000000 --- a/hapi-fhir-validation/src/test/resources/terminology/OperationOutcome-ValueSet-custom-issue-detail.json +++ /dev/null @@ -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]" - ] - } - ] -} \ No newline at end of file