Merge branch 'master' into 2024-04-gg-lookup
This commit is contained in:
commit
0d7c837b85
|
@ -89,7 +89,6 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ibm.icu</groupId>
|
<groupId>com.ibm.icu</groupId>
|
||||||
<artifactId>icu4j</artifactId>
|
<artifactId>icu4j</artifactId>
|
||||||
|
@ -107,18 +106,21 @@
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.bytebuddy</groupId>
|
<groupId>net.bytebuddy</groupId>
|
||||||
<artifactId>byte-buddy</artifactId>
|
<artifactId>byte-buddy</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -126,12 +128,14 @@
|
||||||
<artifactId>junit-vintage-engine</artifactId>
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
<version>${junit_jupiter_version}</version>
|
<version>${junit_jupiter_version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-params</artifactId>
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -139,6 +143,7 @@
|
||||||
<artifactId>junit-platform-launcher</artifactId>
|
<artifactId>junit-platform-launcher</artifactId>
|
||||||
<version>${junit_platform_launcher_version}</version>
|
<version>${junit_platform_launcher_version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -146,13 +151,14 @@
|
||||||
<artifactId>fhir-test-cases</artifactId>
|
<artifactId>fhir-test-cases</artifactId>
|
||||||
<version>${validator_test_case_version}</version>
|
<version>${validator_test_case_version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.13.2</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -161,14 +167,13 @@
|
||||||
<version>3.1.0</version>
|
<version>3.1.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
<artifactId>mockwebserver</artifactId>
|
<artifactId>mockwebserver</artifactId>
|
||||||
<version>4.11.0</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
|
|
@ -7499,7 +7499,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
|
|
||||||
// first case: the type value set is wrong for primitive special types
|
// first case: the type value set is wrong for primitive special types
|
||||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||||
if (iss.getDetails().getText().startsWith("Unable to resolve system - value set expansion has no matches for code 'http://hl7.org/fhirpath/System")) {
|
if (iss.hasDetails() && iss.getDetails().getText().startsWith("Unable to resolve system - value set expansion has no matches for code 'http://hl7.org/fhirpath/System")) {
|
||||||
return new ValidationResult("http://hl7.org/fhirpath/System", null, null, null);
|
return new ValidationResult("http://hl7.org/fhirpath/System", null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
package org.hl7.fhir.validation.special;
|
||||||
|
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import org.hl7.fhir.r5.formats.JsonParser;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.formats.IParser;
|
||||||
|
import org.hl7.fhir.r5.model.*;
|
||||||
|
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||||
|
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||||
|
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
||||||
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||||
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class TxServiceTestHelper {
|
||||||
|
|
||||||
|
|
||||||
|
public static String getDiffForValidation(String id, IWorkerContext context, String name, Resource requestParameters, String expectedResponse, String lang, String fp, JsonObject externals, boolean isCodeSystem) throws JsonSyntaxException, FileNotFoundException, IOException {
|
||||||
|
org.hl7.fhir.r5.model.Parameters p = (org.hl7.fhir.r5.model.Parameters) requestParameters;
|
||||||
|
ValueSet valueSet = null;
|
||||||
|
String valueSetUrl = null;
|
||||||
|
if (!isCodeSystem) {
|
||||||
|
if (p.hasParameter("valueSetVersion")) {
|
||||||
|
valueSetUrl = p.getParameterValue("url").primitiveValue()+"|"+p.getParameterValue("valueSetVersion").primitiveValue();
|
||||||
|
valueSet = context.fetchResource(ValueSet.class, p.getParameterValue("url").primitiveValue(), p.getParameterValue("valueSetVersion").primitiveValue());
|
||||||
|
} else {
|
||||||
|
valueSetUrl = p.getParameterValue("url").primitiveValue();
|
||||||
|
valueSet = context.fetchResource(ValueSet.class, p.getParameterValue("url").primitiveValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValidationResult validationResult = null;
|
||||||
|
String code = null;
|
||||||
|
String system = null;
|
||||||
|
String version = null;
|
||||||
|
String display = null;
|
||||||
|
CodeableConcept codeableConcept = null;
|
||||||
|
org.hl7.fhir.r5.model.Parameters parameters = null;
|
||||||
|
OperationOutcome operationOutcome = null;
|
||||||
|
|
||||||
|
if (valueSet == null && valueSetUrl != null) {
|
||||||
|
String msg = context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, valueSetUrl);
|
||||||
|
operationOutcome = new OperationOutcome();
|
||||||
|
CodeableConcept codeableConceptWhenNullValueSet = operationOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.ERROR).setCode(OperationOutcome.IssueType.NOTFOUND).getDetails();
|
||||||
|
codeableConceptWhenNullValueSet.addCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found", null);
|
||||||
|
codeableConceptWhenNullValueSet.setText(msg);
|
||||||
|
} else {
|
||||||
|
ValidationOptions options = new ValidationOptions(FhirPublication.R5);
|
||||||
|
if (p.hasParameter("displayLanguage")) {
|
||||||
|
options = options.withLanguage(p.getParameterString("displayLanguage"));
|
||||||
|
} else if (lang != null ) {
|
||||||
|
options = options.withLanguage(lang);
|
||||||
|
}
|
||||||
|
if (p.hasParameter("valueset-membership-only") && "true".equals(p.getParameterString("valueset-membership-only"))) {
|
||||||
|
options = options.withCheckValueSetOnly();
|
||||||
|
}
|
||||||
|
if (p.hasParameter("lenient-display-validation") && "true".equals(p.getParameterString("lenient-display-validation"))) {
|
||||||
|
options = options.setDisplayWarningMode(true);
|
||||||
|
}
|
||||||
|
if (p.hasParameter("activeOnly") && "true".equals(p.getParameterString("activeOnly"))) {
|
||||||
|
options = options.setActiveOnly(true);
|
||||||
|
}
|
||||||
|
context.getExpansionParameters().clearParameters("includeAlternateCodes");
|
||||||
|
for (Parameters.ParametersParameterComponent pp : p.getParameter()) {
|
||||||
|
if ("includeAlternateCodes".equals(pp.getName())) {
|
||||||
|
context.getExpansionParameters().addParameter(pp.copy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.hasParameter("code")) {
|
||||||
|
code = p.getParameterString("code");
|
||||||
|
system = p.getParameterString(isCodeSystem ? "url" : "system");
|
||||||
|
version = p.getParameterString(isCodeSystem ? "version" : "systemVersion");
|
||||||
|
display = p.getParameterString("display");
|
||||||
|
validationResult = context.validateCode(options.withGuessSystem(),
|
||||||
|
p.getParameterString(isCodeSystem ? "url" : "system"), p.getParameterString(isCodeSystem ? "version" : "systemVersion"),
|
||||||
|
p.getParameterString("code"), p.getParameterString("display"), valueSet);
|
||||||
|
} else if (p.hasParameter("coding")) {
|
||||||
|
Coding coding = (Coding) p.getParameterValue("coding");
|
||||||
|
code = coding.getCode();
|
||||||
|
system = coding.getSystem();
|
||||||
|
version = coding.getVersion();
|
||||||
|
display = coding.getDisplay();
|
||||||
|
validationResult = context.validateCode(options, coding, valueSet);
|
||||||
|
} else if (p.hasParameter("codeableConcept")) {
|
||||||
|
codeableConcept = (CodeableConcept) p.getParameterValue("codeableConcept");
|
||||||
|
validationResult = context.validateCode(options, codeableConcept, valueSet);
|
||||||
|
} else {
|
||||||
|
throw new Error("validate not done yet for this steup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (operationOutcome == null && validationResult != null && validationResult.getSeverity() == org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.FATAL) {
|
||||||
|
operationOutcome = new OperationOutcome();
|
||||||
|
operationOutcome.getIssue().addAll(validationResult.getIssues());
|
||||||
|
}
|
||||||
|
if (operationOutcome != null) {
|
||||||
|
TxTesterSorters.sortOperationOutcome(operationOutcome);
|
||||||
|
TxTesterScrubbers.scrubOO(operationOutcome, false);
|
||||||
|
|
||||||
|
String actualResponse = new JsonParser().setOutputStyle(IParser.OutputStyle.PRETTY).composeString(operationOutcome);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
writeDiffToFileSystem( name, expectedResponse, actualResponse);
|
||||||
|
|
||||||
|
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
|
||||||
|
if (diff != null) {
|
||||||
|
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
|
||||||
|
TextFile.stringToFile(actualResponse, fp);
|
||||||
|
System.out.println("Test "+name+"failed: "+diff);
|
||||||
|
}
|
||||||
|
return diff;
|
||||||
|
} else {
|
||||||
|
if (parameters == null) {
|
||||||
|
parameters = new org.hl7.fhir.r5.model.Parameters();
|
||||||
|
if (validationResult.getSystem() != null) {
|
||||||
|
parameters.addParameter("system", new UriType(validationResult.getSystem()));
|
||||||
|
} else if (system != null) {
|
||||||
|
parameters.addParameter("system", new UriType(system));
|
||||||
|
}
|
||||||
|
if (validationResult.getCode() != null) {
|
||||||
|
if (code != null && !code.equals(validationResult.getCode())) {
|
||||||
|
parameters.addParameter("code", new CodeType(code));
|
||||||
|
parameters.addParameter("normalized-code", new CodeType(validationResult.getCode()));
|
||||||
|
} else {
|
||||||
|
parameters.addParameter("code", new CodeType(validationResult.getCode()));
|
||||||
|
}
|
||||||
|
} else if (code != null) {
|
||||||
|
parameters.addParameter("code", new CodeType(code));
|
||||||
|
}
|
||||||
|
if (validationResult.getSeverity() == org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.ERROR) {
|
||||||
|
parameters.addParameter("result", false);
|
||||||
|
} else {
|
||||||
|
parameters.addParameter("result", true);
|
||||||
|
}
|
||||||
|
if (validationResult.getMessage() != null) {
|
||||||
|
parameters.addParameter("message", validationResult.getMessage());
|
||||||
|
}
|
||||||
|
if (validationResult.getVersion() != null) {
|
||||||
|
parameters.addParameter("version", validationResult.getVersion());
|
||||||
|
} else if (version != null) {
|
||||||
|
parameters.addParameter("version", new StringType(version));
|
||||||
|
}
|
||||||
|
if (validationResult.getDisplay() != null) {
|
||||||
|
parameters.addParameter("display", validationResult.getDisplay());
|
||||||
|
} else if (display != null) {
|
||||||
|
parameters.addParameter("display", new StringType(display));
|
||||||
|
}
|
||||||
|
// if (vm.getCodeableConcept() != null) {
|
||||||
|
// res.addParameter("codeableConcept", vm.getCodeableConcept());
|
||||||
|
// } else
|
||||||
|
if (codeableConcept != null) {
|
||||||
|
parameters.addParameter("codeableConcept", codeableConcept);
|
||||||
|
}
|
||||||
|
if (validationResult.isInactive()) {
|
||||||
|
parameters.addParameter("inactive", true);
|
||||||
|
}
|
||||||
|
if (validationResult.getStatus() != null) {
|
||||||
|
parameters.addParameter("status", validationResult.getStatus());
|
||||||
|
}
|
||||||
|
if (validationResult.getUnknownSystems() != null) {
|
||||||
|
for (String s : validationResult.getUnknownSystems()) {
|
||||||
|
parameters.addParameter(validationResult.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED ? "x-caused-by-unknown-system" : "x-unknown-system", new CanonicalType(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (validationResult.getIssues().size() > 0) {
|
||||||
|
operationOutcome = new OperationOutcome();
|
||||||
|
operationOutcome.getIssue().addAll(validationResult.getIssues());
|
||||||
|
parameters.addParameter().setName("issues").setResource(operationOutcome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TxTesterSorters.sortParameters(parameters);
|
||||||
|
TxTesterScrubbers.scrubParams(parameters);
|
||||||
|
|
||||||
|
String actualResponse = new JsonParser().setOutputStyle(IParser.OutputStyle.PRETTY).composeString(parameters);
|
||||||
|
|
||||||
|
writeDiffToFileSystem(name, expectedResponse, actualResponse);
|
||||||
|
|
||||||
|
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
|
||||||
|
if (diff != null) {
|
||||||
|
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
|
||||||
|
TextFile.stringToFile(actualResponse, fp);
|
||||||
|
System.out.println("Test "+name+"failed: "+diff);
|
||||||
|
}
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeDiffToFileSystem(String testName, String expected, String actual) throws IOException {
|
||||||
|
String rootDirectory = System.getenv("TX_SERVICE_TEST_DIFF_TARGET");
|
||||||
|
if (rootDirectory == null || rootDirectory.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String fullExpected = rootDirectory + "/expected/";
|
||||||
|
String fullActual = rootDirectory + "/actual/";
|
||||||
|
File expectedDirectory = new File(fullExpected);
|
||||||
|
if (!expectedDirectory.exists()) {
|
||||||
|
expectedDirectory.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
File actualDirectory = new File(fullActual);
|
||||||
|
if (!actualDirectory.exists()) {
|
||||||
|
actualDirectory.mkdirs();
|
||||||
|
}
|
||||||
|
TextFile.stringToFile(expected, fullExpected + testName + ".json");
|
||||||
|
TextFile.stringToFile(actual, fullActual + testName + ".json");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.hl7.fhir.validation.special;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TxTestData {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final JsonObject manifest;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final JsonObject externals;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final List<Object[]> testData;
|
||||||
|
|
||||||
|
private TxTestData(List<Object[]> testData, JsonObject manifest, JsonObject externals) throws IOException {
|
||||||
|
this.testData = testData;
|
||||||
|
this.manifest = manifest;
|
||||||
|
this.externals = externals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxTestData loadTestDataFromDefaultClassPath() throws IOException {
|
||||||
|
String contents = TestingUtilities.loadTestResource("tx", "test-cases.json");
|
||||||
|
String externalSource = TestingUtilities.loadTestResource("tx", "messages-tx.fhir.org.json");
|
||||||
|
JsonObject externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(externalSource);
|
||||||
|
|
||||||
|
Map<String, TxTestSetup> examples = new HashMap<String, TxTestSetup>();
|
||||||
|
JsonObject manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents);
|
||||||
|
for (JsonObject suite : manifest.getJsonObjects("suites")) {
|
||||||
|
if (!"tx.fhir.org".equals(suite.asString("mode"))) {
|
||||||
|
String sn = suite.asString("name");
|
||||||
|
for (JsonObject test : suite.getJsonObjects("tests")) {
|
||||||
|
String tn = test.asString("name");
|
||||||
|
examples.put(sn + "." + tn, new TxTestSetup(suite, test));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> names = new ArrayList<String>(examples.size());
|
||||||
|
names.addAll(examples.keySet());
|
||||||
|
Collections.sort(names);
|
||||||
|
|
||||||
|
List<Object[]> testData = new ArrayList<Object[]>(examples.size());
|
||||||
|
for (String id : names) {
|
||||||
|
testData.add(new Object[]{id, examples.get(id)});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TxTestData(testData, manifest, externals);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.hl7.fhir.validation.special;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||||
|
|
||||||
|
public class TxTestSetup {
|
||||||
|
public TxTestSetup(JsonObject suite, JsonObject test) {
|
||||||
|
this.suite = suite;
|
||||||
|
this.test = test;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private JsonObject suite;
|
||||||
|
@Getter
|
||||||
|
private JsonObject test;
|
||||||
|
|
||||||
|
}
|
|
@ -4,11 +4,6 @@ import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
||||||
|
@ -21,34 +16,27 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
import org.hl7.fhir.r5.formats.JsonParser;
|
import org.hl7.fhir.r5.formats.JsonParser;
|
||||||
import org.hl7.fhir.r5.formats.XmlParser;
|
import org.hl7.fhir.r5.formats.XmlParser;
|
||||||
import org.hl7.fhir.r5.model.CanonicalType;
|
|
||||||
import org.hl7.fhir.r5.model.CodeType;
|
import org.hl7.fhir.r5.model.CodeType;
|
||||||
import org.hl7.fhir.r5.model.StringType;
|
|
||||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
|
||||||
import org.hl7.fhir.r5.model.Constants;
|
import org.hl7.fhir.r5.model.Constants;
|
||||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
|
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
|
||||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
|
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
|
||||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.UriType;
|
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
|
||||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
|
||||||
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
||||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||||
import org.hl7.fhir.utilities.FhirPublication;
|
import org.hl7.fhir.utilities.FhirPublication;
|
||||||
import org.hl7.fhir.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
|
||||||
import org.hl7.fhir.utilities.json.model.JsonObject;
|
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|
||||||
import org.hl7.fhir.validation.ValidationEngine;
|
import org.hl7.fhir.validation.ValidationEngine;
|
||||||
|
import org.hl7.fhir.validation.special.TxServiceTestHelper;
|
||||||
|
import org.hl7.fhir.validation.special.TxTestSetup;
|
||||||
|
import org.hl7.fhir.validation.special.TxTestData;
|
||||||
import org.hl7.fhir.validation.special.TxTesterScrubbers;
|
import org.hl7.fhir.validation.special.TxTesterScrubbers;
|
||||||
import org.hl7.fhir.validation.special.TxTesterSorters;
|
import org.hl7.fhir.validation.special.TxTesterSorters;
|
||||||
import org.hl7.fhir.validation.tests.utilities.TestUtilities;
|
import org.hl7.fhir.validation.tests.utilities.TestUtilities;
|
||||||
|
@ -60,62 +48,30 @@ import org.junit.runners.Parameterized;
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.gson.JsonSyntaxException;
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class TerminologyServiceTests {
|
public class TerminologyServiceTests {
|
||||||
|
|
||||||
public static class JsonObjectPair {
|
|
||||||
public JsonObjectPair(JsonObject suite, JsonObject test) {
|
private static TxTestData testData;
|
||||||
this.suite = suite;
|
|
||||||
this.test = test;
|
|
||||||
}
|
|
||||||
private JsonObject suite;
|
|
||||||
private JsonObject test;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parameters(name = "{index}: id {0}")
|
@Parameters(name = "{index}: id {0}")
|
||||||
public static Iterable<Object[]> data() throws IOException {
|
public static Iterable<Object[]> data() throws IOException {
|
||||||
|
testData = TxTestData.loadTestDataFromDefaultClassPath();
|
||||||
String contents = TestingUtilities.loadTestResource("tx", "test-cases.json");
|
return testData.getTestData();
|
||||||
String externalSource = TestingUtilities.loadTestResource("tx", "messages-tx.fhir.org.json");
|
|
||||||
externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(externalSource);
|
|
||||||
|
|
||||||
Map<String, JsonObjectPair> examples = new HashMap<String, JsonObjectPair>();
|
|
||||||
manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents);
|
|
||||||
for (org.hl7.fhir.utilities.json.model.JsonObject suite : manifest.getJsonObjects("suites")) {
|
|
||||||
if (!"tx.fhir.org".equals(suite.asString("mode"))) {
|
|
||||||
String sn = suite.asString("name");
|
|
||||||
for (org.hl7.fhir.utilities.json.model.JsonObject test : suite.getJsonObjects("tests")) {
|
|
||||||
String tn = test.asString("name");
|
|
||||||
examples.put(sn+"."+tn, new JsonObjectPair(suite, test));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> names = new ArrayList<String>(examples.size());
|
|
||||||
names.addAll(examples.keySet());
|
|
||||||
Collections.sort(names);
|
|
||||||
|
|
||||||
List<Object[]> objects = new ArrayList<Object[]>(examples.size());
|
|
||||||
for (String id : names) {
|
|
||||||
objects.add(new Object[]{id, examples.get(id)});
|
|
||||||
}
|
|
||||||
return objects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static org.hl7.fhir.utilities.json.model.JsonObject manifest;
|
private final TxTestSetup setup;
|
||||||
private static org.hl7.fhir.utilities.json.model.JsonObject externals;
|
private final String version;
|
||||||
private JsonObjectPair setup;
|
private final String name;
|
||||||
private String version;
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
|
|
||||||
private static ValidationEngine baseEngine;
|
private static ValidationEngine baseEngine;
|
||||||
|
|
||||||
public TerminologyServiceTests(String name, JsonObjectPair setup) {
|
public TerminologyServiceTests(String name, TxTestSetup setup) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.setup = setup;
|
this.setup = setup;
|
||||||
version = "5.0.0";
|
version = "5.0.0";
|
||||||
|
@ -128,7 +84,7 @@ public class TerminologyServiceTests {
|
||||||
baseEngine = TestUtilities.getValidationEngineNoTxServer("hl7.fhir.r5.core#5.0.0", FhirPublication.R5, "5.0.0");
|
baseEngine = TestUtilities.getValidationEngineNoTxServer("hl7.fhir.r5.core#5.0.0", FhirPublication.R5, "5.0.0");
|
||||||
}
|
}
|
||||||
ValidationEngine engine = new ValidationEngine(this.baseEngine);
|
ValidationEngine engine = new ValidationEngine(this.baseEngine);
|
||||||
for (String s : setup.suite.forceArray("setup").asStrings()) {
|
for (String s : setup.getSuite().forceArray("setup").asStrings()) {
|
||||||
// System.out.println(s);
|
// System.out.println(s);
|
||||||
Resource res = loadResource(s);
|
Resource res = loadResource(s);
|
||||||
engine.seeResource(res);
|
engine.seeResource(res);
|
||||||
|
@ -137,27 +93,29 @@ public class TerminologyServiceTests {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Resource req = loadResource(setup.test.asString("request"));
|
Resource req = loadResource(setup.test.asString("request"));
|
||||||
String fn = setup.test.has("response:tx.fhir.org") ? setup.test.asString("response:tx.fhir.org") : setup.test.asString("response");
|
String fn = setup.getTest().has("response:tx.fhir.org") ? setup.getTest().asString("response:tx.fhir.org") : setup.getTest().asString("response");
|
||||||
String resp = TestingUtilities.loadTestResource("tx", fn);
|
String resp = TestingUtilities.loadTestResource("tx", fn);
|
||||||
String fp = Utilities.path("[tmp]", "tx", fn);
|
String fp = Utilities.path("[tmp]", "tx", fn);
|
||||||
JsonObject ext = externals == null ? null : externals.getJsonObject(fn);
|
JsonObject ext = testData.getExternals() == null ? null : testData.getExternals().getJsonObject(fn);
|
||||||
File fo = ManagedFileAccess.file(fp);
|
File fo = ManagedFileAccess.file(fp);
|
||||||
if (fo.exists()) {
|
if (fo.exists()) {
|
||||||
fo.delete();
|
fo.delete();
|
||||||
}
|
}
|
||||||
if (setup.test.has("profile")) {
|
if (setup.getTest().has("profile")) {
|
||||||
engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource(setup.test.asString("profile")));
|
engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource(setup.getTest().asString("profile")));
|
||||||
} else {
|
} else {
|
||||||
engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource("parameters-default.json"));
|
engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource("parameters-default.json"));
|
||||||
}
|
}
|
||||||
if (setup.test.asString("operation").equals("expand")) {
|
if (setup.getTest().asString("operation").equals("expand")) {
|
||||||
expand(setup.test.str("name"), engine, req, resp, setup.test.asString("Content-Language"), fp, ext);
|
expand(setup.getTest().str("name"), engine, req, resp, setup.getTest().asString("Content-Language"), fp, ext);
|
||||||
} else if (setup.test.asString("operation").equals("validate-code")) {
|
} else if (setup.getTest().asString("operation").equals("validate-code")) {
|
||||||
validate(setup.test.str("name"), engine, setup.test.asString("name"), req, resp, setup.test.asString("Content-Language"), fp, ext, false);
|
String diff = TxServiceTestHelper.getDiffForValidation(setup.getTest().str("name"), engine.getContext(), setup.getTest().asString("name"), req, resp, setup.getTest().asString("Content-Language"), fp, ext, false);
|
||||||
} else if (setup.test.asString("operation").equals("cs-validate-code")) {
|
assertNull(diff, diff);
|
||||||
validate(setup.test.str("name"), engine, setup.test.asString("name"), req, resp, setup.test.asString("Content-Language"), fp, ext, true);
|
} else if (setup.getTest().asString("operation").equals("cs-validate-code")) {
|
||||||
|
String diff = TxServiceTestHelper.getDiffForValidation(setup.getTest().str("name"), engine.getContext(), setup.getTest().asString("name"), req, resp, setup.getTest().asString("Content-Language"), fp, ext, true);
|
||||||
|
assertNull(diff, diff);
|
||||||
} else {
|
} else {
|
||||||
Assertions.fail("Unknown Operation "+setup.test.asString("operation"));
|
Assertions.fail("Unknown Operation "+ setup.getTest().asString("operation"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,167 +205,7 @@ public class TerminologyServiceTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validate(String id, ValidationEngine engine, String name, Resource req, String resp, String lang, String fp, JsonObject ext, boolean isCS) throws JsonSyntaxException, FileNotFoundException, IOException {
|
|
||||||
org.hl7.fhir.r5.model.Parameters p = (org.hl7.fhir.r5.model.Parameters) req;
|
|
||||||
ValueSet vs = null;
|
|
||||||
String vsurl = null;
|
|
||||||
if (!isCS) {
|
|
||||||
if (p.hasParameter("valueSetVersion")) {
|
|
||||||
vsurl = p.getParameterValue("url").primitiveValue()+"|"+p.getParameterValue("valueSetVersion").primitiveValue();
|
|
||||||
vs = engine.getContext().fetchResource(ValueSet.class, p.getParameterValue("url").primitiveValue(), p.getParameterValue("valueSetVersion").primitiveValue());
|
|
||||||
} else {
|
|
||||||
vsurl = p.getParameterValue("url").primitiveValue();
|
|
||||||
vs = engine.getContext().fetchResource(ValueSet.class, p.getParameterValue("url").primitiveValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValidationResult vm = null;
|
|
||||||
String code = null;
|
|
||||||
String system = null;
|
|
||||||
String version = null;
|
|
||||||
String display = null;
|
|
||||||
CodeableConcept cc = null;
|
|
||||||
org.hl7.fhir.r5.model.Parameters res = null;
|
|
||||||
OperationOutcome oo = null;
|
|
||||||
|
|
||||||
if (vs == null && vsurl != null) {
|
|
||||||
String msg = engine.getContext().formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, vsurl);
|
|
||||||
oo = new OperationOutcome();
|
|
||||||
CodeableConcept cct = oo.addIssue().setSeverity(IssueSeverity.ERROR).setCode(IssueType.NOTFOUND).getDetails();
|
|
||||||
cct.addCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found", null);
|
|
||||||
cct.setText(msg);
|
|
||||||
} else {
|
|
||||||
ValidationOptions options = new ValidationOptions(FhirPublication.R5);
|
|
||||||
if (p.hasParameter("displayLanguage")) {
|
|
||||||
options = options.withLanguage(p.getParameterString("displayLanguage"));
|
|
||||||
} else if (lang != null ) {
|
|
||||||
options = options.withLanguage(lang);
|
|
||||||
}
|
|
||||||
if (p.hasParameter("valueset-membership-only") && "true".equals(p.getParameterString("valueset-membership-only"))) {
|
|
||||||
options = options.withCheckValueSetOnly();
|
|
||||||
}
|
|
||||||
if (p.hasParameter("lenient-display-validation") && "true".equals(p.getParameterString("lenient-display-validation"))) {
|
|
||||||
options = options.setDisplayWarningMode(true);
|
|
||||||
}
|
|
||||||
if (p.hasParameter("activeOnly") && "true".equals(p.getParameterString("activeOnly"))) {
|
|
||||||
options = options.setActiveOnly(true);
|
|
||||||
}
|
|
||||||
engine.getContext().getExpansionParameters().clearParameters("includeAlternateCodes");
|
|
||||||
for (ParametersParameterComponent pp : p.getParameter()) {
|
|
||||||
if ("includeAlternateCodes".equals(pp.getName())) {
|
|
||||||
engine.getContext().getExpansionParameters().addParameter(pp.copy());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p.hasParameter("code")) {
|
|
||||||
code = p.getParameterString("code");
|
|
||||||
system = p.getParameterString(isCS ? "url" : "system");
|
|
||||||
version = p.getParameterString(isCS ? "version" : "systemVersion");
|
|
||||||
display = p.getParameterString("display");
|
|
||||||
vm = engine.getContext().validateCode(options.withGuessSystem(),
|
|
||||||
p.getParameterString(isCS ? "url" : "system"), p.getParameterString(isCS ? "version" : "systemVersion"),
|
|
||||||
p.getParameterString("code"), p.getParameterString("display"), vs);
|
|
||||||
} else if (p.hasParameter("coding")) {
|
|
||||||
Coding coding = (Coding) p.getParameterValue("coding");
|
|
||||||
code = coding.getCode();
|
|
||||||
system = coding.getSystem();
|
|
||||||
version = coding.getVersion();
|
|
||||||
display = coding.getDisplay();
|
|
||||||
vm = engine.getContext().validateCode(options, coding, vs);
|
|
||||||
} else if (p.hasParameter("codeableConcept")) {
|
|
||||||
cc = (CodeableConcept) p.getParameterValue("codeableConcept");
|
|
||||||
vm = engine.getContext().validateCode(options, cc, vs);
|
|
||||||
} else {
|
|
||||||
throw new Error("validate not done yet for this steup");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oo == null && vm != null && vm.getSeverity() == org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.FATAL) {
|
|
||||||
oo = new OperationOutcome();
|
|
||||||
oo.getIssue().addAll(vm.getIssues());
|
|
||||||
}
|
|
||||||
if (oo != null) {
|
|
||||||
TxTesterSorters.sortOperationOutcome(oo);
|
|
||||||
TxTesterScrubbers.scrubOO(oo, false);
|
|
||||||
|
|
||||||
String pj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
|
|
||||||
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, ext);
|
|
||||||
if (diff != null) {
|
|
||||||
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
|
|
||||||
TextFile.stringToFile(pj, fp);
|
|
||||||
System.out.println("Test "+name+"failed: "+diff);
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(diff == null, diff);
|
|
||||||
} else {
|
|
||||||
if (res == null) {
|
|
||||||
res = new org.hl7.fhir.r5.model.Parameters();
|
|
||||||
if (vm.getSystem() != null) {
|
|
||||||
res.addParameter("system", new UriType(vm.getSystem()));
|
|
||||||
} else if (system != null) {
|
|
||||||
res.addParameter("system", new UriType(system));
|
|
||||||
}
|
|
||||||
if (vm.getCode() != null) {
|
|
||||||
if (code != null && !code.equals(vm.getCode())) {
|
|
||||||
res.addParameter("code", new CodeType(code));
|
|
||||||
res.addParameter("normalized-code", new CodeType(vm.getCode()));
|
|
||||||
} else {
|
|
||||||
res.addParameter("code", new CodeType(vm.getCode()));
|
|
||||||
}
|
|
||||||
} else if (code != null) {
|
|
||||||
res.addParameter("code", new CodeType(code));
|
|
||||||
}
|
|
||||||
if (vm.getSeverity() == org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.ERROR) {
|
|
||||||
res.addParameter("result", false);
|
|
||||||
} else {
|
|
||||||
res.addParameter("result", true);
|
|
||||||
}
|
|
||||||
if (vm.getMessage() != null) {
|
|
||||||
res.addParameter("message", vm.getMessage());
|
|
||||||
}
|
|
||||||
if (vm.getVersion() != null) {
|
|
||||||
res.addParameter("version", vm.getVersion());
|
|
||||||
} else if (version != null) {
|
|
||||||
res.addParameter("version", new StringType(version));
|
|
||||||
}
|
|
||||||
if (vm.getDisplay() != null) {
|
|
||||||
res.addParameter("display", vm.getDisplay());
|
|
||||||
} else if (display != null) {
|
|
||||||
res.addParameter("display", new StringType(display));
|
|
||||||
}
|
|
||||||
// if (vm.getCodeableConcept() != null) {
|
|
||||||
// res.addParameter("codeableConcept", vm.getCodeableConcept());
|
|
||||||
// } else
|
|
||||||
if (cc != null) {
|
|
||||||
res.addParameter("codeableConcept", cc);
|
|
||||||
}
|
|
||||||
if (vm.isInactive()) {
|
|
||||||
res.addParameter("inactive", true);
|
|
||||||
}
|
|
||||||
if (vm.getStatus() != null) {
|
|
||||||
res.addParameter("status", vm.getStatus());
|
|
||||||
}
|
|
||||||
if (vm.getUnknownSystems() != null) {
|
|
||||||
for (String s : vm.getUnknownSystems()) {
|
|
||||||
res.addParameter(vm.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED ? "x-caused-by-unknown-system" : "x-unknown-system", new CanonicalType(s));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vm.getIssues().size() > 0) {
|
|
||||||
oo = new OperationOutcome();
|
|
||||||
oo.getIssue().addAll(vm.getIssues());
|
|
||||||
res.addParameter().setName("issues").setResource(oo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TxTesterSorters.sortParameters(res);
|
|
||||||
TxTesterScrubbers.scrubParams(res);
|
|
||||||
|
|
||||||
String pj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(res);
|
|
||||||
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, ext);
|
|
||||||
if (diff != null) {
|
|
||||||
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
|
|
||||||
TextFile.stringToFile(pj, fp);
|
|
||||||
System.out.println("Test "+name+"failed: "+diff);
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(diff == null, diff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
||||||
String contents = TestingUtilities.loadTestResource("tx", filename);
|
String contents = TestingUtilities.loadTestResource("tx", filename);
|
||||||
|
|
Loading…
Reference in New Issue