mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-30 11:58:55 +00:00
Upload Terminology with Endpoint Validation (#4035)
* add failing test * Fix doc upload issue * Add change log yaml file * update due to review from Nathan Co-authored-by: nathaniel.doef <nathaniel.doef@smilecdr.com> Co-authored-by: weiping202209 <weiping.yang@smilecdr.com>
This commit is contained in:
parent
e4a2285f30
commit
31e13e6adb
@ -38,6 +38,7 @@ import org.apache.commons.cli.ParseException;
|
|||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.io.input.CountingInputStream;
|
import org.apache.commons.io.input.CountingInputStream;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.ICompositeType;
|
import org.hl7.fhir.instance.model.api.ICompositeType;
|
||||||
@ -242,10 +243,11 @@ public class UploadTerminologyCommand extends BaseRequestGeneratingCommand {
|
|||||||
|
|
||||||
byte[] bytes = theBytes;
|
byte[] bytes = theBytes;
|
||||||
String fileName = theFileName;
|
String fileName = theFileName;
|
||||||
|
String suffix = fileName.substring(fileName.lastIndexOf("."));
|
||||||
|
|
||||||
if (bytes.length > ourTransferSizeLimit) {
|
if (bytes.length > ourTransferSizeLimit) {
|
||||||
ourLog.info("File size is greater than {} - Going to use a local file reference instead of a direct HTTP transfer. Note that this will only work when executing this command on the same server as the FHIR server itself.", FileUtil.formatFileSize(ourTransferSizeLimit));
|
ourLog.info("File size is greater than {} - Going to use a local file reference instead of a direct HTTP transfer. Note that this will only work when executing this command on the same server as the FHIR server itself.", FileUtil.formatFileSize(ourTransferSizeLimit));
|
||||||
String suffix = fileName.substring(fileName.lastIndexOf("."));
|
|
||||||
try {
|
try {
|
||||||
File tempFile = File.createTempFile("hapi-fhir-cli", suffix);
|
File tempFile = File.createTempFile("hapi-fhir-cli", suffix);
|
||||||
tempFile.deleteOnExit();
|
tempFile.deleteOnExit();
|
||||||
@ -260,6 +262,7 @@ public class UploadTerminologyCommand extends BaseRequestGeneratingCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ICompositeType attachment = AttachmentUtil.newInstance(myFhirCtx);
|
ICompositeType attachment = AttachmentUtil.newInstance(myFhirCtx);
|
||||||
|
AttachmentUtil.setContentType(myFhirCtx, attachment, getContentType(suffix));
|
||||||
AttachmentUtil.setUrl(myFhirCtx, attachment, fileName);
|
AttachmentUtil.setUrl(myFhirCtx, attachment, fileName);
|
||||||
if (bytes != null) {
|
if (bytes != null) {
|
||||||
AttachmentUtil.setData(myFhirCtx, attachment, bytes);
|
AttachmentUtil.setData(myFhirCtx, attachment, bytes);
|
||||||
@ -267,6 +270,25 @@ public class UploadTerminologyCommand extends BaseRequestGeneratingCommand {
|
|||||||
ParametersUtil.addParameterToParameters(myFhirCtx, theInputParameters, TerminologyUploaderProvider.PARAM_FILE, attachment);
|
ParametersUtil.addParameterToParameters(myFhirCtx, theInputParameters, TerminologyUploaderProvider.PARAM_FILE, attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Files may be included in the attachment as raw CSV/JSON/XML files, or may also be combined into a compressed ZIP file.
|
||||||
|
* Content Type reference: https://smilecdr.com/docs/terminology/uploading.html#delta-add-operation
|
||||||
|
*/
|
||||||
|
private String getContentType(String theSuffix) {
|
||||||
|
String retVal = "";
|
||||||
|
if(StringUtils.isNotBlank(theSuffix)) {
|
||||||
|
switch (theSuffix.toLowerCase()) {
|
||||||
|
case "csv" : retVal = "text/csv"; break;
|
||||||
|
case "xml" : retVal = "application/xml"; break;
|
||||||
|
case "json" : retVal = "application/json"; break;
|
||||||
|
case "zip" : retVal = "application/zip"; break;
|
||||||
|
default: retVal = "text/plain";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ourLog.debug("File suffix given was {} and contentType is {}, defaulting to content type text/plain", theSuffix, retVal);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
private enum ModeEnum {
|
private enum ModeEnum {
|
||||||
SNAPSHOT, ADD, REMOVE
|
SNAPSHOT, ADD, REMOVE
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
package ca.uhn.fhir.cli;
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||||
import ca.uhn.fhir.jpa.term.UploadStatistics;
|
import ca.uhn.fhir.jpa.term.UploadStatistics;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||||
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.BaseRestServerHelper;
|
import ca.uhn.fhir.test.utilities.BaseRestServerHelper;
|
||||||
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
import ca.uhn.fhir.test.utilities.RestServerDstu3Helper;
|
||||||
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
|
||||||
|
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -460,6 +467,19 @@ public class UploadTerminologyCommandTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("paramsProvider")
|
@MethodSource("paramsProvider")
|
||||||
public void testUploadICD10UsingCompressedFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
public void testUploadICD10UsingCompressedFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
|
uploadICD10UsingCompressedFile(theFhirVersion, theIncludeTls);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("paramsProvider")
|
||||||
|
public void testUploadTerminologyWithEndpointValidation(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
|
RequestValidatingInterceptor requestValidatingInterceptor = createRequestValidatingInterceptor();
|
||||||
|
myBaseRestServerHelper.registerInterceptor(requestValidatingInterceptor);
|
||||||
|
|
||||||
|
uploadICD10UsingCompressedFile(theFhirVersion, theIncludeTls);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadICD10UsingCompressedFile(String theFhirVersion, boolean theIncludeTls) throws IOException {
|
||||||
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
if (FHIR_VERSION_DSTU3.equals(theFhirVersion)) {
|
||||||
when(myTermLoaderSvc.loadIcd10cm(anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
when(myTermLoaderSvc.loadIcd10cm(anyList(), any())).thenReturn(new UploadStatistics(100, new org.hl7.fhir.dstu3.model.IdType("CodeSystem/101")));
|
||||||
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
} else if (FHIR_VERSION_R4.equals(theFhirVersion)) {
|
||||||
@ -486,6 +506,23 @@ public class UploadTerminologyCommandTest {
|
|||||||
assertThat(IOUtils.toByteArray(listOfDescriptors.get(0).getInputStream()).length, greaterThan(100));
|
assertThat(IOUtils.toByteArray(listOfDescriptors.get(0).getInputStream()).length, greaterThan(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RequestValidatingInterceptor createRequestValidatingInterceptor(){
|
||||||
|
FhirInstanceValidator fhirInstanceValidator = new FhirInstanceValidator(myCtx);
|
||||||
|
ValidationSupportChain validationSupport = new ValidationSupportChain(
|
||||||
|
new DefaultProfileValidationSupport(myCtx),
|
||||||
|
new InMemoryTerminologyServerValidationSupport(myCtx),
|
||||||
|
new CommonCodeSystemsTerminologyService(myCtx)
|
||||||
|
);
|
||||||
|
|
||||||
|
fhirInstanceValidator.setValidationSupport(validationSupport);
|
||||||
|
FhirValidator fhirValidator = myCtx.newValidator();
|
||||||
|
fhirValidator.registerValidatorModule(fhirInstanceValidator);
|
||||||
|
|
||||||
|
RequestValidatingInterceptor requestValidatingInterceptor = new RequestValidatingInterceptor();
|
||||||
|
requestValidatingInterceptor.setValidatorModules(List.of(fhirInstanceValidator));
|
||||||
|
return requestValidatingInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void writeConceptAndHierarchyFiles() throws IOException {
|
private synchronized void writeConceptAndHierarchyFiles() throws IOException {
|
||||||
if (!myConceptsFile.exists()) {
|
if (!myConceptsFile.exists()) {
|
||||||
try (FileWriter w = new FileWriter(myConceptsFile, false)) {
|
try (FileWriter w = new FileWriter(myConceptsFile, false)) {
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 4091
|
||||||
|
jira: SMILE-3977
|
||||||
|
title: "Previously, when the upload-terminology command was used to upload a terminology file with endpoint validation enabled, a validation error occurred due to a missing file content type.
|
||||||
|
This has been fixed by specifying the file content type of the uploaded file."
|
Loading…
x
Reference in New Issue
Block a user