more revisions to tests

This commit is contained in:
Grahame Grieve 2023-08-19 20:18:15 +10:00
parent 497a81a544
commit e4f6ec5a7b
8 changed files with 125 additions and 68 deletions

View File

@ -363,9 +363,13 @@ public class CodeSystemUtilities {
}
public static boolean isInactive(CodeSystem cs, ConceptDefinitionComponent def) throws FHIRException {
StandardsStatus ss = ToolingExtensions.getStandardsStatus(def);
if (ss == StandardsStatus.DEPRECATED || ss == StandardsStatus.WITHDRAWN) {
return true;
}
for (ConceptPropertyComponent p : def.getProperty()) {
if ("status".equals(p.getCode()) && p.hasValueStringType()) {
return "inactive".equals(p.getValueStringType().primitiveValue()) || "retired".equals(p.getValueStringType().primitiveValue());
return "inactive".equals(p.getValueStringType().primitiveValue()) || "retired".equals(p.getValueStringType().primitiveValue()) || "deprecated".equals(p.getValueStringType().primitiveValue());
}
if ("inactive".equals(p.getCode()) && p.hasValueBooleanType()) {
return p.getValueBooleanType().getValue();
@ -886,6 +890,10 @@ public class CodeSystemUtilities {
public static DataType getProperty(CodeSystem cs, String code, String property) {
ConceptDefinitionComponent def = getCode(cs, code);
return getProperty(cs, def, property);
}
public static DataType getProperty(CodeSystem cs, ConceptDefinitionComponent def, String property) {
ConceptPropertyComponent cp = getProperty(def, property);
return cp == null ? null : cp.getValue();
}
@ -905,5 +913,18 @@ public class CodeSystemUtilities {
}
return false;
}
public static String getStatus(CodeSystem cs, ConceptDefinitionComponent cc) {
StandardsStatus ss = ToolingExtensions.getStandardsStatus(cc);
if (ss == StandardsStatus.DEPRECATED || ss == StandardsStatus.WITHDRAWN) {
return ss.toCode();
}
DataType v = getProperty(cs, cc, "status");
if (v == null || !v.isPrimitive()) {
return null;
} else {
return v.primitiveValue();
}
}
}

View File

@ -13,12 +13,12 @@ import java.util.ArrayList;
public class TerminologyOperationContext {
public class TerminologyServiceProtectionException extends FHIRException {
public static class TerminologyServiceProtectionException extends FHIRException {
private TerminologyServiceErrorClass error;
private IssueType type;
protected TerminologyServiceProtectionException(String message, TerminologyServiceErrorClass error, IssueType type) {
public TerminologyServiceProtectionException(String message, TerminologyServiceErrorClass error, IssueType type) {
super(message);
this.error = error;
this.type = type;

View File

@ -143,7 +143,7 @@ public class ValueSetProcessBase {
}
private List<OperationOutcomeIssueComponent> makeStatusIssue(String path, String id, String msg, CanonicalResource resource) {
List<OperationOutcomeIssueComponent> iss = makeIssue(IssueSeverity.INFORMATION, IssueType.EXPIRED, path, context.formatMessage(msg, resource.getVersionedUrl()));
List<OperationOutcomeIssueComponent> iss = makeIssue(IssueSeverity.INFORMATION, IssueType.BUSINESSRULE, path, context.formatMessage(msg, resource.getVersionedUrl()));
// this is a testing hack - see TerminologyServiceTests
iss.get(0).setUserData("status-msg-name", "warning-"+id);

View File

@ -81,6 +81,7 @@ import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
import org.hl7.fhir.r5.terminologies.providers.SpecialCodeSystem;
import org.hl7.fhir.r5.terminologies.providers.URICodeSystem;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.TerminologyServiceProtectionException;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.terminologies.utilities.ValueSetProcessBase;
import org.hl7.fhir.r5.utils.ToolingExtensions;
@ -195,6 +196,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
ValidationProcessInfo info = new ValidationProcessInfo();
CodeableConcept vcc = new CodeableConcept();
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
int i = 0;
for (Coding c : code.getCoding()) {
@ -262,6 +264,9 @@ public class ValueSetValidator extends ValueSetProcessBase {
info.getIssues().addAll(makeIssue(IssueSeverity.ERROR, IssueType.CODEINVALID, path, msg));
}
}
if (vcc.hasCoding() && code.hasText()) {
vcc.setText(code.getText());
}
if (!checkRequiredSupplements(info)) {
return new ValidationResult(IssueSeverity.ERROR, info.getIssues().get(info.getIssues().size()-1).getDetails().getText(), info.getIssues());
} else if (info.hasErrors()) {
@ -295,7 +300,8 @@ public class ValueSetValidator extends ValueSetProcessBase {
private boolean checkRequiredSupplements(ValidationProcessInfo info) {
if (!requiredSupplements.isEmpty()) {
info.getIssues().addAll(makeIssue(IssueSeverity.ERROR, IssueType.NOTFOUND, null, context.formatMessagePlural(requiredSupplements.size(), I18nConstants.VALUESET_SUPPLEMENT_MISSING, CommaSeparatedStringBuilder.build(requiredSupplements))));
String msg= context.formatMessagePlural(requiredSupplements.size(), I18nConstants.VALUESET_SUPPLEMENT_MISSING, CommaSeparatedStringBuilder.build(requiredSupplements));
throw new TerminologyServiceProtectionException(msg, TerminologyServiceErrorClass.BUSINESS_RULE, IssueType.NOTFOUND);
}
return requiredSupplements.isEmpty();
}
@ -529,6 +535,8 @@ public class ValueSetValidator extends ValueSetProcessBase {
res.setMessage("Code found in include, however: " + res.getMessage());
res.getIssues().addAll(makeIssue(IssueSeverity.WARNING, IssueType.EXCEPTION, path, res.getMessage()));
}
} else if (res == null) {
res = new ValidationResult(system, wv, null, null);
}
} else if ((res != null && !res.isOk())) {
String msg = context.formatMessagePlural(1, I18nConstants.NONE_OF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET_, valueset.getVersionedUrl(), code.toString());
@ -676,18 +684,19 @@ public class ValueSetValidator extends ValueSetProcessBase {
if (vcc != null) {
vcc.addCoding(vc);
}
if (CodeSystemUtilities.isInactive(cs, cc)) {
info.addIssue(makeIssue(IssueSeverity.WARNING, IssueType.EXPIRED, path, context.formatMessage(I18nConstants.INACTIVE_CODE_WARNING, cc.getCode())));
}
boolean inactive = (CodeSystemUtilities.isInactive(cs, cc));
String status = inactive ? (CodeSystemUtilities.getStatus(cs, cc)) : null;
boolean ws = false;
if (code.getDisplay() == null) {
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, vc.getDisplay());
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, vc.getDisplay()).setStatus(inactive, status);
}
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(", ", " or ");
if (cc.hasDisplay() && isOkLanguage(cs.getLanguage())) {
b.append("'"+cc.getDisplay()+"'");
if (code.getDisplay().equalsIgnoreCase(cc.getDisplay())) {
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs));
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs)).setStatus(inactive, status);
} else if (Utilities.normalize(code.getDisplay()).equals(Utilities.normalize(cc.getDisplay()))) {
ws = true;
}
@ -698,7 +707,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
if (isOkLanguage(ds.getLanguage())) {
b.append("'"+ds.getValue()+"'");
if (code.getDisplay().equalsIgnoreCase(ds.getValue())) {
return new ValidationResult(code.getSystem(),cs.getVersion(), cc, getPreferredDisplay(cc, cs));
return new ValidationResult(code.getSystem(),cs.getVersion(), cc, getPreferredDisplay(cc, cs)).setStatus(inactive, status);
}
if (Utilities.normalize(code.getDisplay()).equalsIgnoreCase(Utilities.normalize(ds.getValue()))) {
ws = true;
@ -712,7 +721,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
if (vs.getCc().hasDisplay() && isOkLanguage(vs.getValueset().getLanguage())) {
b.append("'"+vs.getCc().getDisplay()+"'");
if (code.getDisplay().equalsIgnoreCase(vs.getCc().getDisplay())) {
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs));
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs)).setStatus(inactive, status);
}
}
for (ConceptReferenceDesignationComponent ds : vs.getCc().getDesignation()) {
@ -720,7 +729,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
if (isOkLanguage(ds.getLanguage())) {
b.append("'"+ds.getValue()+"'");
if (code.getDisplay().equalsIgnoreCase(ds.getValue())) {
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs));
return new ValidationResult(code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs)).setStatus(inactive, status);
}
}
}
@ -728,10 +737,10 @@ public class ValueSetValidator extends ValueSetProcessBase {
}
if (b.count() == 0) {
String msg = context.formatMessagePlural(options.getLanguages().size(), I18nConstants.NO_VALID_DISPLAY_FOUND, code.getSystem(), code.getCode(), code.getDisplay(), options.langSummary());
return new ValidationResult(IssueSeverity.WARNING, msg, code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs), makeIssue(IssueSeverity.WARNING, IssueType.INVALID, path+".display", msg));
return new ValidationResult(IssueSeverity.WARNING, msg, code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs), makeIssue(IssueSeverity.WARNING, IssueType.INVALID, path+".display", msg)).setStatus(inactive, status);
} else {
String msg = context.formatMessagePlural(b.count(), ws ? I18nConstants.DISPLAY_NAME_WS_FOR__SHOULD_BE_ONE_OF__INSTEAD_OF : I18nConstants.DISPLAY_NAME_FOR__SHOULD_BE_ONE_OF__INSTEAD_OF, code.getSystem(), code.getCode(), b.toString(), code.getDisplay(), options.langSummary());
return new ValidationResult(dispWarningStatus(), msg, code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs), makeIssue(dispWarning(), IssueType.INVALID, path+".display", msg));
return new ValidationResult(dispWarningStatus(), msg, code.getSystem(), cs.getVersion(), cc, getPreferredDisplay(cc, cs), makeIssue(dispWarning(), IssueType.INVALID, path+".display", msg)).setStatus(inactive, status);
}
}

View File

@ -255,7 +255,7 @@ public class TxTester {
TxTesterSorters.sortValueSet(vs);
vsj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(vs);
} catch (EFhirClientException e) {
OperationOutcome oo = e.getServerErrors().get(0);
OperationOutcome oo = e.getServerError();
TxTesterScrubbers.scrubOO(oo, tight);
vsj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
}
@ -279,7 +279,7 @@ public class TxTester {
TxTesterSorters.sortParameters(po);
pj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(po);
} catch (EFhirClientException e) {
OperationOutcome oo = e.getServerErrors().get(0);
OperationOutcome oo = e.getServerError();
oo.setText(null);
pj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
}

View File

@ -31,6 +31,10 @@ public class TxTesterSorters {
}
public static void sortOperationOutcome(OperationOutcome oo) {
Collections.sort(oo.getIssue(), new TxTesterSorters.OperationIssueSorter());
}
public static void sortValueSet(ValueSet vs) {
Collections.sort(vs.getExtension(), new TxTesterSorters.ExtensionSorter());
if (vs.hasExpansion()) {

View File

@ -95,7 +95,7 @@ public class TerminologyServiceTests {
List<Object[]> objects = new ArrayList<Object[]>(examples.size());
for (String id : names) {
objects.add(new Object[]{id, examples.get(id)});
objects.add(new Object[]{id, examples.get(id)});
}
return objects;
}
@ -208,6 +208,7 @@ public class TerminologyServiceTests {
}
e.getDetails().setText(vse.getError());
oo.addIssue(e);
TxTesterSorters.sortOperationOutcome(oo);
TxTesterScrubbers.scrubOO(oo, false);
String ooj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
@ -242,7 +243,7 @@ public class TerminologyServiceTests {
options = options.withLanguage(p.getParameterString("displayLanguage"));
}
if (p.hasParameter("valueSetMode") && "CHECK_MEMBERSHIP_ONLY".equals(p.getParameterString("valueSetMode"))) {
options = options.withCheckValueSetOnly();
options = options.withCheckValueSetOnly();
}
if (p.hasParameter("mode") && "lenient-display-validation".equals(p.getParameterString("mode"))) {
options = options.setDisplayWarningMode(true);
@ -265,51 +266,73 @@ public class TerminologyServiceTests {
} else {
throw new Error("validate not done yet for this steup");
}
org.hl7.fhir.r5.model.Parameters res = new org.hl7.fhir.r5.model.Parameters();
if (vm.getSystem() != null) {
res.addParameter("system", new UriType(vm.getSystem()));
}
if (vm.getCode() != null) {
res.addParameter("code", new CodeType(vm.getCode()));
}
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());
}
if (vm.getDisplay() != null) {
res.addParameter("display", vm.getDisplay());
}
if (vm.getCodeableConcept() != null) {
res.addParameter("codeableConcept", vm.getCodeableConcept());
}
if (vm.getUnknownSystems() != null) {
for (String s : vm.getUnknownSystems()) {
res.addParameter("x-caused-by-unknown-system", new CanonicalType(s));
}
}
if (vm.getIssues().size() > 0) {
if (vm.getSeverity() == org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.FATAL) {
OperationOutcome oo = new OperationOutcome();
oo.getIssue().addAll(vm.getIssues());
res.addParameter().setName("issues").setResource(oo);
}
TxTesterSorters.sortParameters(res);
TxTesterScrubbers.scrubParams(res);
TxTesterSorters.sortOperationOutcome(oo);
TxTesterScrubbers.scrubOO(oo, false);
String pj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(res);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, pj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
System.out.println("Test "+name+"failed: "+diff);
String pj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
String diff = CompareUtilities.checkJsonSrcIsSame(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 {
org.hl7.fhir.r5.model.Parameters res = new org.hl7.fhir.r5.model.Parameters();
if (vm.getSystem() != null) {
res.addParameter("system", new UriType(vm.getSystem()));
}
if (vm.getCode() != null) {
res.addParameter("code", new CodeType(vm.getCode()));
}
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());
}
if (vm.getDisplay() != null) {
res.addParameter("display", vm.getDisplay());
}
if (vm.getCodeableConcept() != null) {
res.addParameter("codeableConcept", vm.getCodeableConcept());
}
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("x-caused-by-unknown-system", new CanonicalType(s));
}
}
if (vm.getIssues().size() > 0) {
OperationOutcome 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(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);
}
Assertions.assertTrue(diff == null, diff);
}
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {