Merge pull request #1399 from hapifhir/2023-08-gg-tx-tests-externals-2
2023 08 gg tx tests externals 2
This commit is contained in:
commit
46bae75c40
|
@ -5,6 +5,7 @@
|
|||
* Add checking around internal status consistency and across dependencies (draft/experimental/retired/deprecated)
|
||||
* Improved error messages on server failure
|
||||
* Fix bug in warning about No valid Display Names found
|
||||
* Use Supplements when validating display names
|
||||
* Fix issue in FHIRPath .combine focus handling
|
||||
* Check Extension fixed values for URLs - enforce consistency
|
||||
* Fix R4 FML parser problem
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.hl7.fhir.convertors.txClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
|
@ -8,10 +9,12 @@ import java.util.Map;
|
|||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r4.model.Resource;
|
||||
import org.hl7.fhir.r4.utils.client.EFhirClientException;
|
||||
import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
|
@ -93,16 +96,38 @@ public class TerminologyClientR4 implements ITerminologyClient {
|
|||
|
||||
@Override
|
||||
public Parameters validateCS(Parameters pin) throws FHIRException {
|
||||
org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin);
|
||||
p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "validate-code", p2);
|
||||
return (Parameters) VersionConvertorFactory_40_50.convertResource(p2);
|
||||
try {
|
||||
org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin);
|
||||
p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "validate-code", p2);
|
||||
return (Parameters) VersionConvertorFactory_40_50.convertResource(p2);
|
||||
} catch (EFhirClientException e) {
|
||||
if (e.getServerErrors().size() == 1) {
|
||||
OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0));
|
||||
throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getMessage(), op, e);
|
||||
} else {
|
||||
throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getMessage(), e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parameters validateVS(Parameters pin) throws FHIRException {
|
||||
org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin);
|
||||
p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2);
|
||||
return (Parameters) VersionConvertorFactory_40_50.convertResource(p2);
|
||||
try {
|
||||
org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin);
|
||||
p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2);
|
||||
return (Parameters) VersionConvertorFactory_40_50.convertResource(p2);
|
||||
} catch (EFhirClientException e) {
|
||||
if (e.getServerErrors().size() == 1) {
|
||||
OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0));
|
||||
throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getMessage(), op, e);
|
||||
} else {
|
||||
throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getMessage(), e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -522,37 +522,31 @@ public class FHIRToolingClient {
|
|||
complex = complex || !(p.getValue() instanceof PrimitiveType);
|
||||
Parameters searchResults = null;
|
||||
String ps = "";
|
||||
try {
|
||||
if (!complex)
|
||||
for (ParametersParameterComponent p : params.getParameter())
|
||||
if (p.getValue() instanceof PrimitiveType)
|
||||
ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&";
|
||||
ResourceRequest<T> result;
|
||||
if (complex)
|
||||
result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps),
|
||||
utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())),
|
||||
getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG);
|
||||
else
|
||||
result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps),
|
||||
getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG);
|
||||
result.addErrorStatus(410);// gone
|
||||
result.addErrorStatus(404);// unknown
|
||||
result.addSuccessStatus(200);// Only one for now
|
||||
if (result.isUnsuccessfulRequest())
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
if (result.getPayload() instanceof Parameters)
|
||||
return (Parameters) result.getPayload();
|
||||
else {
|
||||
Parameters p_out = new Parameters();
|
||||
p_out.addParameter().setName("return").setResource(result.getPayload());
|
||||
return p_out;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
handleException(
|
||||
"Error performing tx2 operation '" + name + ": " + e.getMessage() + "' (parameters = \"" + ps + "\")", e);
|
||||
if (!complex)
|
||||
for (ParametersParameterComponent p : params.getParameter())
|
||||
if (p.getValue() instanceof PrimitiveType)
|
||||
ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&";
|
||||
ResourceRequest<T> result;
|
||||
if (complex)
|
||||
result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps),
|
||||
utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())),
|
||||
getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG);
|
||||
else
|
||||
result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps),
|
||||
getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG);
|
||||
result.addErrorStatus(410);// gone
|
||||
result.addErrorStatus(404);// unknown
|
||||
result.addSuccessStatus(200);// Only one for now
|
||||
if (result.isUnsuccessfulRequest())
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
if (result.getPayload() instanceof Parameters)
|
||||
return (Parameters) result.getPayload();
|
||||
else {
|
||||
Parameters p_out = new Parameters();
|
||||
p_out.addParameter().setName("return").setResource(result.getPayload());
|
||||
return p_out;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Bundle transaction(Bundle batch) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.hl7.fhir.r4.terminologies;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
@ -29,9 +31,11 @@ package org.hl7.fhir.r4.terminologies;
|
|||
|
||||
*/
|
||||
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r4.context.HTMLClientLogger;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
|
@ -65,12 +69,20 @@ public class TerminologyClientR4 implements TerminologyClient {
|
|||
|
||||
@Override
|
||||
public Parameters validateCS(Parameters pin) {
|
||||
return client.operateType(CodeSystem.class, "validate-code", pin);
|
||||
try {
|
||||
return client.operateType(CodeSystem.class, "validate-code", pin);
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parameters validateVS(Parameters pin) {
|
||||
return client.operateType(ValueSet.class, "validate-code", pin);
|
||||
try {
|
||||
return client.operateType(ValueSet.class, "validate-code", pin);
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -278,42 +278,36 @@ public class FHIRToolingClient {
|
|||
return result.getPayload();
|
||||
}
|
||||
|
||||
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
|
||||
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) throws IOException {
|
||||
boolean complex = false;
|
||||
for (ParametersParameterComponent p : params.getParameter())
|
||||
complex = complex || !(p.getValue() instanceof PrimitiveType);
|
||||
String ps = "";
|
||||
try {
|
||||
if (!complex)
|
||||
for (ParametersParameterComponent p : params.getParameter())
|
||||
if (p.getValue() instanceof PrimitiveType)
|
||||
ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&";
|
||||
ResourceRequest<T> result;
|
||||
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
|
||||
if (complex) {
|
||||
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
|
||||
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
|
||||
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
} else {
|
||||
result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(),
|
||||
"GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
if (result.getPayload() instanceof Parameters) {
|
||||
return (Parameters) result.getPayload();
|
||||
} else {
|
||||
Parameters p_out = new Parameters();
|
||||
p_out.addParameter().setName("return").setResource(result.getPayload());
|
||||
return p_out;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
handleException(
|
||||
"Error performing tx4 operation '" + name + ": " + e.getMessage() + "' (parameters = \"" + ps + "\")", e);
|
||||
if (!complex)
|
||||
for (ParametersParameterComponent p : params.getParameter())
|
||||
if (p.getValue() instanceof PrimitiveType)
|
||||
ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&";
|
||||
ResourceRequest<T> result;
|
||||
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
|
||||
if (complex) {
|
||||
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
|
||||
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
|
||||
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
} else {
|
||||
result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(),
|
||||
"GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
if (result.getPayload() instanceof Parameters) {
|
||||
return (Parameters) result.getPayload();
|
||||
} else {
|
||||
Parameters p_out = new Parameters();
|
||||
p_out.addParameter().setName("return").setResource(result.getPayload());
|
||||
return p_out;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Bundle transaction(Bundle batch) {
|
||||
|
@ -390,16 +384,16 @@ public class FHIRToolingClient {
|
|||
parameters.put("url", vsUrl);
|
||||
|
||||
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
|
||||
try {
|
||||
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", parameters),
|
||||
getPreferredResourceFormat(), generateHeaders(), "ValueSet/$expand?url=" + vsUrl, TIMEOUT_OPERATION_EXPAND);
|
||||
try {
|
||||
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", parameters),
|
||||
getPreferredResourceFormat(), generateHeaders(), "ValueSet/$expand?url=" + vsUrl, TIMEOUT_OPERATION_EXPAND);
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result == null ? null : (ValueSet) result.getPayload();
|
||||
}
|
||||
|
||||
|
@ -416,7 +410,7 @@ public class FHIRToolingClient {
|
|||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
return result == null ? null : (ValueSet) result.getPayload();
|
||||
}
|
||||
|
@ -427,7 +421,7 @@ public class FHIRToolingClient {
|
|||
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params),
|
||||
getPreferredResourceFormat(), generateHeaders(), "CodeSystem/$lookup", TIMEOUT_NORMAL);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
|
@ -455,7 +449,7 @@ public class FHIRToolingClient {
|
|||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
return result == null ? null : (ValueSet) result.getPayload();
|
||||
}
|
||||
|
@ -478,7 +472,7 @@ public class FHIRToolingClient {
|
|||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
return result == null ? null : (ConceptMap) result.getPayload();
|
||||
}
|
||||
|
@ -498,7 +492,7 @@ public class FHIRToolingClient {
|
|||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
return result == null ? null : (ConceptMap) result.getPayload();
|
||||
}
|
||||
|
|
|
@ -306,7 +306,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
} catch (Exception e) {
|
||||
throw new FHIRException(formatMessage(canNoTS
|
||||
? I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER_USE_PARAMETER_TX_NA_TUN_RUN_WITHOUT_USING_TERMINOLOGY_SERVICES_TO_VALIDATE_LOINC_SNOMED_ICDX_ETC_ERROR__
|
||||
: I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage()), e);
|
||||
: I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage(), client.getAddress()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1197,7 +1197,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR, e.getType());
|
||||
iss.getDetails().setText(e.getMessage());
|
||||
issues.add(iss);
|
||||
return new ValidationResult(IssueSeverity.ERROR, e.getMessage(), e.getError(), issues);
|
||||
return new ValidationResult(IssueSeverity.FATAL, e.getMessage(), e.getError(), issues);
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
localError = e.getMessage();
|
||||
|
@ -1354,6 +1354,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
Set<String> unknownSystems = new HashSet<>();
|
||||
|
||||
List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
|
||||
String localError = null;
|
||||
String localWarning = null;
|
||||
|
||||
if (options.isUseClient()) {
|
||||
// ok, first we try to validate locally
|
||||
try {
|
||||
|
@ -1365,14 +1370,37 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
}
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof NoTerminologyServiceException) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, "No Terminology Service", TerminologyServiceErrorClass.NOSERVICE, null);
|
||||
} catch (VSCheckerException e) {
|
||||
if (e.isWarning()) {
|
||||
localWarning = e.getMessage();
|
||||
} else {
|
||||
localError = e.getMessage();
|
||||
}
|
||||
if (e.getIssues() != null) {
|
||||
issues.addAll(e.getIssues());
|
||||
}
|
||||
} catch (TerminologyServiceProtectionException e) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR, e.getType());
|
||||
iss.getDetails().setText(e.getMessage());
|
||||
issues.add(iss);
|
||||
return new ValidationResult(IssueSeverity.FATAL, e.getMessage(), e.getError(), issues);
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
localError = e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if (localError != null && tcc.getClient() == null) {
|
||||
if (unknownSystems.size() > 0) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues).setUnknownSystems(unknownSystems);
|
||||
} else {
|
||||
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues);
|
||||
}
|
||||
}
|
||||
if (localWarning != null && tcc.getClient() == null) {
|
||||
return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER, localWarning), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, issues);
|
||||
}
|
||||
|
||||
if (!options.isUseServer()) {
|
||||
return new ValidationResult(IssueSeverity.WARNING, "Unable to validate code without using server", TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, null);
|
||||
}
|
||||
|
@ -1499,6 +1527,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
String system = null;
|
||||
String code = null;
|
||||
String version = null;
|
||||
boolean inactive = false;
|
||||
String status = null;
|
||||
List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
|
||||
TerminologyServiceErrorClass err = TerminologyServiceErrorClass.UNKNOWN;
|
||||
|
@ -1516,18 +1546,22 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
version = ((PrimitiveType<?>) p.getValue()).asStringValue();
|
||||
} else if (p.getName().equals("code")) {
|
||||
code = ((PrimitiveType<?>) p.getValue()).asStringValue();
|
||||
} else if (p.getName().equals("inactive")) {
|
||||
inactive = "true".equals(((PrimitiveType<?>) p.getValue()).asStringValue());
|
||||
} else if (p.getName().equals("status")) {
|
||||
status = ((PrimitiveType<?>) p.getValue()).asStringValue();
|
||||
} else if (p.getName().equals("x-caused-by-unknown-system")) {
|
||||
err = TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED;
|
||||
} else if (p.getName().equals("warning-withdrawn")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.BUSINESSRULE);
|
||||
iss.getDetails().setText(formatMessage(vs == null ? I18nConstants.MSG_WITHDRAWN : I18nConstants.MSG_WITHDRAWN_SRC, ((PrimitiveType<?>) p.getValue()).asStringValue(), vs));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("warning-deprecated")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.BUSINESSRULE);
|
||||
iss.getDetails().setText(formatMessage(vs == null ? I18nConstants.MSG_DEPRECATED : I18nConstants.MSG_DEPRECATED_SRC, ((PrimitiveType<?>) p.getValue()).asStringValue(), vs));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("warning-retired")) {
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED);
|
||||
OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.BUSINESSRULE);
|
||||
iss.getDetails().setText(formatMessage(vs == null ? I18nConstants.MSG_RETIRED : I18nConstants.MSG_RETIRED_SRC, ((PrimitiveType<?>) p.getValue()).asStringValue(), vs));
|
||||
issues.add(iss);
|
||||
} else if (p.getName().equals("warning-experimental")) {
|
||||
|
@ -1565,7 +1599,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
} else {
|
||||
res = new ValidationResult(system, version, new ConceptDefinitionComponent().setCode(code), null).setTxLink(txLog.getLastId());
|
||||
}
|
||||
res.setIssues(issues );
|
||||
res.setIssues(issues);
|
||||
res.setStatus(inactive, status);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,8 @@ public interface IWorkerContext {
|
|||
private List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
private CodeableConcept codeableConcept;
|
||||
private Set<String> unknownSystems;
|
||||
private boolean inactive;
|
||||
private String status;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -339,6 +341,22 @@ public interface IWorkerContext {
|
|||
|
||||
}
|
||||
|
||||
public boolean isInactive() {
|
||||
return inactive;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public ValidationResult setStatus(boolean inactive, String status) {
|
||||
this.inactive = inactive;
|
||||
if (!"inactive".equals(status)) {
|
||||
this.status = status;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CodingValidationRequest {
|
||||
|
|
|
@ -341,7 +341,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
setTxCaps(capabilityStatement);
|
||||
return capabilitiesStatementQuick.getSoftware().getVersion();
|
||||
} catch (Exception e) {
|
||||
throw new FHIRException(formatMessage(canNoTS ? I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER_USE_PARAMETER_TX_NA_TUN_RUN_WITHOUT_USING_TERMINOLOGY_SERVICES_TO_VALIDATE_LOINC_SNOMED_ICDX_ETC_ERROR__ : I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage()), e);
|
||||
throw new FHIRException(formatMessage(canNoTS ? I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER_USE_PARAMETER_TX_NA_TUN_RUN_WITHOUT_USING_TERMINOLOGY_SERVICES_TO_VALIDATE_LOINC_SNOMED_ICDX_ETC_ERROR__ : I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage(), client.getAddress()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ValidationProcessInfo {
|
|||
public void setErr(TerminologyServiceErrorClass err) {
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
|
||||
public List<OperationOutcomeIssueComponent> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
|
|
|
@ -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 ws = false;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,19 +57,12 @@ import org.hl7.fhir.r5.model.OperationOutcome;
|
|||
*/
|
||||
public class EFhirClientException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private List<OperationOutcome> errors = new ArrayList<OperationOutcome>();
|
||||
private OperationOutcome error = null;
|
||||
|
||||
public EFhirClientException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EFhirClientException(String message, List<OperationOutcome> serverErrors) {
|
||||
super(message);
|
||||
if(serverErrors != null && serverErrors.size() > 0) {
|
||||
errors.addAll(serverErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public EFhirClientException(Exception cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
@ -86,12 +79,23 @@ public class EFhirClientException extends RuntimeException {
|
|||
* @param serverError
|
||||
*/
|
||||
public EFhirClientException(String message, OperationOutcome serverError) {
|
||||
super(message);
|
||||
if(serverError != null) {
|
||||
errors.add(serverError);
|
||||
}
|
||||
super(message);
|
||||
error = serverError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate EFhirClientException which include a message indicating the cause of the exception
|
||||
* along with any OperationOutcome server error that may have resulted.
|
||||
*
|
||||
* @param message
|
||||
* @param serverError
|
||||
*/
|
||||
public EFhirClientException(String message, OperationOutcome serverError, Exception cause) {
|
||||
super(message, cause);
|
||||
error = serverError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate EFhirClientException indicating the cause of the exception
|
||||
* along with any OperationOutcome server error the server may have generated.
|
||||
|
@ -103,19 +107,11 @@ public class EFhirClientException extends RuntimeException {
|
|||
*/
|
||||
public EFhirClientException(OperationOutcome serverError) {
|
||||
super("Error on the server: "+serverError.getText().getDiv().allText()+". Refer to e.getServerErrors() for additional details.");
|
||||
if(serverError != null) {
|
||||
errors.add(serverError);
|
||||
}
|
||||
error = serverError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method returns all OperationOutcome server errors that are
|
||||
* associated with this exception.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<OperationOutcome> getServerErrors() {
|
||||
return errors;
|
||||
public OperationOutcome getServerError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,8 +119,8 @@ public class EFhirClientException extends RuntimeException {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hasServerErrors() {
|
||||
return errors.size() > 0;
|
||||
public boolean hasServerError() {
|
||||
return error != null;
|
||||
}
|
||||
|
||||
}
|
|
@ -421,16 +421,16 @@ public class FHIRToolingClient {
|
|||
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
|
||||
try {
|
||||
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"),
|
||||
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())),
|
||||
getPreferredResourceFormat(),
|
||||
generateHeaders(),
|
||||
"ValueSet/$expand?url=" + source.getUrl(),
|
||||
TIMEOUT_OPERATION_EXPAND);
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload());
|
||||
}
|
||||
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())),
|
||||
getPreferredResourceFormat(),
|
||||
generateHeaders(),
|
||||
"ValueSet/$expand?url=" + source.getUrl(),
|
||||
TIMEOUT_OPERATION_EXPAND);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload());
|
||||
}
|
||||
return result == null ? null : (ValueSet) result.getPayload();
|
||||
}
|
||||
|
|
|
@ -962,7 +962,10 @@ public class I18nConstants {
|
|||
public static final String MSG_RETIRED_SRC = "MSG_RETIRED_SRC";
|
||||
public static final String MSG_DRAFT_SRC = "MSG_DRAFT_SRC";
|
||||
public static final String MSG_EXPERIMENTAL_SRC = "MSG_EXPERIMENTAL_SRC";
|
||||
public static final String INACTIVE_CODE_WARNING = "INACTIVE_CODE_WARNING";
|
||||
public static final String STATUS_CODE_WARNING = "STATUS_CODE_WARNING";
|
||||
public static final String STATUS_CODE_HINT = "STATUS_CODE_HINT";
|
||||
public static final String STATUS_CODE_WARNING_CODE = "STATUS_CODE_WARNING_CODE";
|
||||
public static final String STATUS_CODE_HINT_CODE = "STATUS_CODE_HINT_CODE";
|
||||
public static final String SD_EXTENSION_URL_MISSING = "SD_EXTENSION_URL_MISSING";
|
||||
public static final String MSG_DEPENDS_ON_DEPRECATED = "MSG_DEPENDS_ON_DEPRECATED";
|
||||
public static final String MSG_DEPENDS_ON_WITHDRAWN = "MSG_DEPENDS_ON_WITHDRAWN";
|
||||
|
|
|
@ -465,7 +465,7 @@ Parser_Type__not_supported = Parser Type {0} not supported
|
|||
Version_mismatch_The_context_has_version__loaded_and_the_new_content_being_loaded_is_version_ = Version mismatch. The context has version {0} loaded, and the new content being loaded is version {1}
|
||||
Error_reading__from_package__ = Error reading {0} from package {1}#{2}: {3}
|
||||
Error_parsing_ = Error parsing {0}:{1}
|
||||
Unable_to_connect_to_terminology_server_Use_parameter_tx_na_tun_run_without_using_terminology_services_to_validate_LOINC_SNOMED_ICDX_etc_Error__ = Unable to connect to terminology server. Use parameter ''-tx n/a'' to run without using terminology services to validate LOINC, SNOMED, ICD-X etc. Error = {0}
|
||||
Unable_to_connect_to_terminology_server_Use_parameter_tx_na_tun_run_without_using_terminology_services_to_validate_LOINC_SNOMED_ICDX_etc_Error__ = Unable to connect to terminology server at {1}. Use parameter ''-tx n/a'' to run without using terminology services to validate LOINC, SNOMED, ICD-X etc. Error = {0}
|
||||
Display_Name_for__should_be_one_of__instead_of_one = Wrong Display Name ''{4}'' for {1}#{2} - should be {3} (for the language(s) ''{5}'')
|
||||
Display_Name_for__should_be_one_of__instead_of_other = Wrong Display Name ''{4}'' for {1}#{2} - should be one of {0} choices: {3} (for the language(s) ''{5}'')
|
||||
Display_Name_WS_for__should_be_one_of__instead_of_one = Wrong whitespace in Display Name ''{4}'' for {1}#{2} - should be {3} (for the language(s) ''{5}'')
|
||||
|
@ -697,7 +697,7 @@ UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLIC
|
|||
UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator ({0}) for slice {1}
|
||||
SD_NESTED_MUST_SUPPORT_DIFF = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support. The inner must-supports will be ignored unless the element inherits must-support = true
|
||||
SD_NESTED_MUST_SUPPORT_SNAPSHOT = The element {0} has types/profiles/targets that are marked as must support, but the element itself is not marked as must-support
|
||||
Unable_to_connect_to_terminology_server = Unable to connect to terminology server. Error = {0}
|
||||
Unable_to_connect_to_terminology_server = Unable to connect to terminology server at {1}. Error = {0}
|
||||
SD_ED_TYPE_PROFILE_UNKNOWN = Unable to resolve profile {0}
|
||||
SD_ED_TYPE_PROFILE_NOTYPE = Found profile {0}, but unable to determine the type it applies to
|
||||
SD_ED_TYPE_PROFILE_WRONG = Profile {0} is for type {1}, but the {3} element has type {2}
|
||||
|
@ -1020,7 +1020,10 @@ MSG_WITHDRAWN_SRC = Reference to withdrawn item {0} from {1}
|
|||
MSG_RETIRED_SRC = Reference to retired item {0} from {1}
|
||||
MSG_EXPERIMENTAL_SRC = Reference to experimental item {0} from {1}
|
||||
MSG_DRAFT_SRC = Reference to draft item {0} from {1}
|
||||
INACTIVE_CODE_WARNING = The code ''{0}'' is valid but is not active
|
||||
STATUS_CODE_WARNING = The code is valid but is {0}
|
||||
STATUS_CODE_HINT = The code is {0}
|
||||
STATUS_CODE_WARNING_CODE = The code ''{1}'' is valid but is {0}
|
||||
STATUS_CODE_HINT_CODE = The code ''{1}'' is {0}
|
||||
SD_ED_TYPE_PROFILE_WRONG_TYPE_one = The type {0} is not in the list of allowed type {1} in the profile {2}
|
||||
SD_ED_TYPE_PROFILE_WRONG_TYPE_other = The type {0} is not in the list of allowed types {1} in the profile {2}
|
||||
MSG_DEPENDS_ON_DEPRECATED = The {0} {1} is deprecated
|
||||
|
|
|
@ -60,6 +60,7 @@ import org.hl7.fhir.r5.model.Resource;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
|
@ -634,6 +635,24 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
|
||||
*
|
||||
* @param thePass
|
||||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected void txIssue(List<ValidationMessage> errors, String ruleDate, String txLink, int line, int col, String path, OperationOutcomeIssueComponent issue) {
|
||||
IssueType code = IssueType.fromCode(issue.getCode().toCode());
|
||||
IssueSeverity severity = IssueSeverity.fromCode(issue.getSeverity().toCode());
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, code, line, col, path, issue.getDetails().getText(), severity).setTxLink(txLink);
|
||||
// if (checkMsgId(msg, vmsg)) {
|
||||
errors.add(vmsg);
|
||||
// }
|
||||
// }
|
||||
// return thePass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails. Also, keep track of it later in case we want to remove it if we find a required binding for this element later
|
||||
*
|
||||
|
@ -1312,17 +1331,17 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
if (standardsStatus == StandardsStatus.DEPRECATED) {
|
||||
if (!statusWarnings.contains(vurl+":DEPRECATED")) {
|
||||
statusWarnings.add(vurl+":DEPRECATED");
|
||||
hint(errors, "2023-08-10", IssueType.EXPIRED, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_DEPRECATED, type, vurl);
|
||||
hint(errors, "2023-08-10", IssueType.BUSINESSRULE, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_DEPRECATED, type, vurl);
|
||||
}
|
||||
} else if (standardsStatus == StandardsStatus.WITHDRAWN) {
|
||||
if (!statusWarnings.contains(vurl+":WITHDRAWN")) {
|
||||
statusWarnings.add(vurl+":WITHDRAWN");
|
||||
hint(errors, "2023-08-10", IssueType.EXPIRED, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_WITHDRAWN, type, vurl);
|
||||
hint(errors, "2023-08-10", IssueType.BUSINESSRULE, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_WITHDRAWN, type, vurl);
|
||||
}
|
||||
} else if (ex.getStatus() == PublicationStatus.RETIRED) {
|
||||
if (!statusWarnings.contains(vurl+":RETIRED")) {
|
||||
statusWarnings.add(vurl+":RETIRED");
|
||||
hint(errors, "2023-08-10", IssueType.EXPIRED, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_RETIRED, type, vurl);
|
||||
hint(errors, "2023-08-10", IssueType.BUSINESSRULE, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_RETIRED, type, vurl);
|
||||
}
|
||||
} else if (false && warnOnDraftOrExperimental && source != null) {
|
||||
// for now, this is disabled; these warnings are just everywhere, and it's an intractible problem.
|
||||
|
|
|
@ -125,6 +125,7 @@ import org.hl7.fhir.r5.model.ImplementationGuide;
|
|||
import org.hl7.fhir.r5.model.ImplementationGuide.ImplementationGuideGlobalComponent;
|
||||
import org.hl7.fhir.r5.model.InstantType;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.r5.model.Period;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Quantity;
|
||||
|
@ -1024,9 +1025,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
|
||||
if (s == null)
|
||||
return true;
|
||||
if (s != null && s.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : s.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", s.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
if (s.isOk()) {
|
||||
if (s.getMessage() != null)
|
||||
txWarning(errors, NO_RULE_DATE, s.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, s == null, I18nConstants.TERMINOLOGY_PASSTHROUGH_TX_MESSAGE, s.getMessage(), system, code);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (s.getErrorClass() != null && s.getErrorClass().isInfrastructure())
|
||||
|
@ -1279,6 +1286,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// ignore this since we can't validate but it doesn't matter..
|
||||
} else {
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, cc, true); // we're going to validate the codings directly, so only check the valueset
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
if (!vr.isOk()) {
|
||||
bindingsOk = false;
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
|
||||
|
@ -1356,6 +1368,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
public void checkBindings(List<ValidationMessage> errors, String path, Element element, NodeStack stack, ValueSet valueset, Coding nextCoding) {
|
||||
if (isNotBlank(nextCoding.getCode()) && isNotBlank(nextCoding.getSystem()) && context.supportsSystem(nextCoding.getSystem())) {
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, nextCoding, false);
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
if (vr.getSeverity() != null/* && vr.hasMessage()*/) {
|
||||
if (vr.getSeverity() == IssueSeverity.INFORMATION) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
|
@ -1416,6 +1433,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// ignore this since we can't validate but it doesn't matter..
|
||||
} else {
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, cc, false); // we're going to validate the codings directly
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
if (!vr.isOk()) {
|
||||
bindingsOk = false;
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
|
||||
|
@ -1465,6 +1487,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
String nextVersion = nextCoding.getVersion();
|
||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
ValidationResult vr = checkCodeOnServer(stack, nextCode, nextSystem, nextVersion, null, false);
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
if (!vr.isOk()) {
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_NOTVALID, nextCode, nextSystem);
|
||||
}
|
||||
|
@ -1528,7 +1555,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (binding.getStrength() == BindingStrength.REQUIRED) {
|
||||
removeTrackedMessagesForLocation(errors, element, path);
|
||||
}
|
||||
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
|
||||
if (vr != null && !vr.isOk()) {
|
||||
if (vr.IsNoService())
|
||||
|
@ -1671,6 +1702,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, cc, false);
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
timeTracker.tx(t, "vc "+cc.toString());
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1708,6 +1744,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, c, true);
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
|
||||
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1737,6 +1779,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = checkCodeOnServer(stack, valueset, value, baseOptions.withLanguage(stack.getWorkingLang()));
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
timeTracker.tx(t, "vc "+value);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
|
@ -1788,7 +1835,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (theSystem != null && theCode != null && !noTerminologyChecks) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, theSystem) && ok;
|
||||
try {
|
||||
if (checkCode(errors, element, path, theCode, theSystem, theVersion, theDisplay, checkDisplay, stack))
|
||||
if (checkCode(errors, element, path, theCode, theSystem, theVersion, theDisplay, checkDisplay, stack)) {
|
||||
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
|
||||
|
@ -1809,6 +1856,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
vr = checkCodeOnServer(stack, valueset, c, true);
|
||||
}
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
|
||||
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED) {
|
||||
removeTrackedMessagesForLocation(errors, element, path);
|
||||
|
@ -1862,6 +1915,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) e.printStackTrace();
|
||||
rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODING2, e.getMessage(), e.toString());
|
||||
|
@ -3120,6 +3176,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
vr = checkCodeOnServer(stack, vs, value, options);
|
||||
}
|
||||
if (vr != null && vr.isOk()) {
|
||||
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
|
||||
txIssue(errors, "2023-08-19", vr.getTxLink(), element.line(), element.col(), path, iss);
|
||||
}
|
||||
}
|
||||
|
||||
timeTracker.tx(t, "vc "+value+"");
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED) {
|
||||
removeTrackedMessagesForLocation(errors, element, path);
|
||||
|
@ -6565,7 +6627,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet vs, String value, ValidationOptions options) {
|
||||
return context.validateCode(options, value, vs);
|
||||
return checkForInctive(context.validateCode(options, value, vs));
|
||||
}
|
||||
|
||||
// no delay on this one?
|
||||
|
@ -6578,27 +6640,52 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
lang = "en"; // ubiquitious default languauge
|
||||
}
|
||||
codingObserver.seeCode(stack, system, version, code, display);
|
||||
return context.validateCode(baseOptions.withLanguage(lang), system, version, code, checkDisplay ? display : null);
|
||||
return checkForInctive(context.validateCode(baseOptions.withLanguage(lang), system, version, code, checkDisplay ? display : null));
|
||||
}
|
||||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, Coding c, boolean checkMembership) {
|
||||
codingObserver.seeCode(stack, c);
|
||||
if (checkMembership) {
|
||||
return context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withCheckValueSetOnly(), c, valueset);
|
||||
return checkForInctive( context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withCheckValueSetOnly(), c, valueset));
|
||||
} else {
|
||||
return context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withNoCheckValueSetMembership(), c, valueset);
|
||||
return checkForInctive(context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withNoCheckValueSetMembership(), c, valueset));
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc, boolean vsOnly) {
|
||||
codingObserver.seeCode(stack, cc);
|
||||
if (vsOnly) {
|
||||
return context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withCheckValueSetOnly(), cc, valueset);
|
||||
return checkForInctive(context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()).withCheckValueSetOnly(), cc, valueset));
|
||||
} else {
|
||||
return context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset);
|
||||
return checkForInctive(context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset));
|
||||
}
|
||||
}
|
||||
|
||||
private ValidationResult checkForInctive(ValidationResult res) {
|
||||
if (res == null) {
|
||||
return null;
|
||||
}
|
||||
if (!res.isInactive()) {
|
||||
return res;
|
||||
}
|
||||
org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity lvl = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION;
|
||||
var status = "not active";
|
||||
if (res.getStatus() != null) {
|
||||
status = res.getStatus();
|
||||
}
|
||||
String code = res.getCode();
|
||||
var op = new OperationOutcomeIssueComponent(lvl, org.hl7.fhir.r5.model.OperationOutcome.IssueType.INVALID);
|
||||
String msgId = null;
|
||||
if (code != null) {
|
||||
msgId = res.isOk() ? I18nConstants.STATUS_CODE_WARNING_CODE : I18nConstants.STATUS_CODE_HINT_CODE;
|
||||
} else {
|
||||
msgId = res.isOk() ? I18nConstants.STATUS_CODE_WARNING : I18nConstants.STATUS_CODE_HINT;
|
||||
}
|
||||
op.getDetails().setText(context.formatMessage(msgId, status, code));
|
||||
res.getIssues().add(op);
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean isSecurityChecks() {
|
||||
return securityChecks;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,12 @@ 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()) {
|
||||
|
|
|
@ -78,7 +78,7 @@ public class TerminologyServiceTests {
|
|||
String contents = TestingUtilities.loadTestResource("tx", "test-cases.json");
|
||||
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")) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public class TerminologyServiceTests {
|
|||
private JsonObjectPair setup;
|
||||
private String version;
|
||||
private String name;
|
||||
|
||||
|
||||
|
||||
private static ValidationEngine baseEngine;
|
||||
|
||||
|
@ -114,7 +114,7 @@ public class TerminologyServiceTests {
|
|||
this.setup = setup;
|
||||
version = "5.0.0";
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
@ -208,8 +208,9 @@ 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);
|
||||
String diff = CompareUtilities.checkJsonSrcIsSame(resp, ooj, ext);
|
||||
if (diff != null) {
|
||||
|
@ -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.sortOperationOutcome(oo);
|
||||
TxTesterScrubbers.scrubOO(oo, false);
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hl7.fhir.r5.elementmodel.Manager;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
import org.hl7.fhir.utilities.settings.FhirSettings;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.model.FileInfo;
|
||||
|
@ -60,7 +61,7 @@ class ValidationServiceTest {
|
|||
List<FileInfo> filesToValidate = new ArrayList<>();
|
||||
filesToValidate.add(new FileInfo().setFileName("test_resource.json").setFileContent(resource).setFileType(Manager.FhirFormat.JSON.getExtension()));
|
||||
|
||||
ValidationRequest request = new ValidationRequest().setCliContext(new CliContext().setTxCache(getTerminologyCacheDirectory("validationService"))).setFilesToValidate(filesToValidate);
|
||||
ValidationRequest request = new ValidationRequest().setCliContext(new CliContext().setTxServer(FhirSettings.getTxFhirDevelopment()).setTxCache(getTerminologyCacheDirectory("validationService"))).setFilesToValidate(filesToValidate);
|
||||
// Validation run 1...nothing cached yet
|
||||
myService.validateSources(request);
|
||||
verify(sessionCache, Mockito.times(1)).cacheSession(ArgumentMatchers.any(ValidationEngine.class));
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.hl7.fhir.r4.context.SimpleWorkerContext;
|
|||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.SystemExitManager;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.settings.FhirSettings;
|
||||
import org.hl7.fhir.validation.ValidatorCli;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -16,7 +17,7 @@ public class CDAValidationTest {
|
|||
String fn = TestingUtilities.tempFile("cda", "cda.xml");
|
||||
TextFile.stringToFile(TestingUtilities.loadTestResource("cda/cda-original.xml"), fn);
|
||||
SystemExitManager.setNoExit(true);
|
||||
ValidatorCli.main(new String[] {fn, "-ig", "hl7.cda.uv.core#current"});
|
||||
ValidatorCli.main(new String[] {fn, "-ig", "hl7.cda.uv.core#current", "-tx", FhirSettings.getTxFhirDevelopment()});
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue