Fix validation for enumerated ValueSets (#1982)
* Allow code validation against enumerated VS * Work on validation * Work on this * Work on tests * Work on validation * Work on tests * Work on validation * Test fixes * Add changelog * For a change * Test fixes
This commit is contained in:
parent
063bf4237c
commit
077ee02771
|
@ -25,6 +25,9 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
public class ConceptValidationOptions {
|
public class ConceptValidationOptions {
|
||||||
|
|
||||||
|
private boolean myValidateDisplay;
|
||||||
|
private boolean myInferSystem;
|
||||||
|
|
||||||
public boolean isInferSystem() {
|
public boolean isInferSystem() {
|
||||||
return myInferSystem;
|
return myInferSystem;
|
||||||
}
|
}
|
||||||
|
@ -34,12 +37,19 @@ public class ConceptValidationOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean myInferSystem;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||||
.append("inferSystem", myInferSystem)
|
.append("inferSystem", myInferSystem)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isValidateDisplay() {
|
||||||
|
return myValidateDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConceptValidationOptions setValidateDisplay(boolean theValidateDisplay) {
|
||||||
|
myValidateDisplay = theValidateDisplay;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ package ca.uhn.fhir.context.support;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.thymeleaf.util.Validate;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -29,6 +31,7 @@ public class ValidationSupportContext {
|
||||||
private final Set<String> myCurrentlyGeneratingSnapshots = new HashSet<>();
|
private final Set<String> myCurrentlyGeneratingSnapshots = new HashSet<>();
|
||||||
|
|
||||||
public ValidationSupportContext(IValidationSupport theRootValidationSupport) {
|
public ValidationSupportContext(IValidationSupport theRootValidationSupport) {
|
||||||
|
Validate.notNull(theRootValidationSupport, "theRootValidationSupport musty not be null");
|
||||||
myRootValidationSupport = theRootValidationSupport;
|
myRootValidationSupport = theRootValidationSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 1982
|
||||||
|
title: The validator will now accept codes that are defined in a ValueSet where the valueset contains an enumeration of
|
||||||
|
codes, and the CodeSystem URL refers to an unknown CodeSystem. This allows successful validation of ValueSets in several
|
||||||
|
IGs that rely on the existence of grammar based systems.
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.api.dao;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -41,31 +42,6 @@ public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> exten
|
||||||
|
|
||||||
void purgeCaches();
|
void purgeCaches();
|
||||||
|
|
||||||
ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept, RequestDetails theRequestDetails);
|
IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept, RequestDetails theRequestDetails);
|
||||||
|
|
||||||
class ValidateCodeResult {
|
|
||||||
private String myDisplay;
|
|
||||||
private String myMessage;
|
|
||||||
private boolean myResult;
|
|
||||||
|
|
||||||
public ValidateCodeResult(boolean theResult, String theMessage, String theDisplay) {
|
|
||||||
super();
|
|
||||||
myResult = theResult;
|
|
||||||
myMessage = theMessage;
|
|
||||||
myDisplay = theDisplay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplay() {
|
|
||||||
return myDisplay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return myMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isResult() {
|
|
||||||
return myResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,8 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||||
|
import static ca.uhn.fhir.jpa.util.LogicUtil.multiXor;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
@ -291,102 +293,14 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
public static String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequest) {
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequest) {
|
||||||
List<IIdType> valueSetIds;
|
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||||
|
|
||||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
|
||||||
boolean haveCoding = theCoding != null && theCoding.isEmpty() == false;
|
|
||||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
|
||||||
|
|
||||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
|
||||||
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
|
||||||
}
|
|
||||||
if (!multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
|
||||||
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean haveIdentifierParam = theValueSetIdentifier != null && theValueSetIdentifier.isEmpty() == false;
|
|
||||||
if (theId != null) {
|
|
||||||
valueSetIds = Collections.singletonList(theId);
|
|
||||||
} else if (haveIdentifierParam) {
|
|
||||||
Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(ValueSet.SP_IDENTIFIER, new TokenParam(null, theValueSetIdentifier.getValue())), theRequest);
|
|
||||||
valueSetIds = new ArrayList<>();
|
|
||||||
for (ResourcePersistentId next : ids) {
|
|
||||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "ValueSet", next);
|
|
||||||
valueSetIds.add(id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (theCode == null || theCode.isEmpty()) {
|
|
||||||
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
|
||||||
}
|
|
||||||
String code = theCode.getValue();
|
|
||||||
String system = toStringOrNull(theSystem);
|
|
||||||
valueSetIds = findCodeSystemIdsContainingSystemAndCode(code, system, theRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IIdType nextId : valueSetIds) {
|
|
||||||
ValueSet expansion = expand(nextId, null, theRequest);
|
|
||||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
|
||||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
|
||||||
if (result != null) {
|
|
||||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
|
||||||
if (!theDisplay.getValue().equals(result.getDisplay())) {
|
|
||||||
return new ValidateCodeResult(false, "Display for code does not match", result.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValidateCodeResult(false, "Code not found", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValidateCodeResult validateCodeIsInContains(List<ExpansionContains> contains, String theSystem, String theCode, CodingDt theCoding,
|
|
||||||
CodeableConceptDt theCodeableConcept) {
|
|
||||||
for (ExpansionContains nextCode : contains) {
|
|
||||||
ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String system = nextCode.getSystem();
|
|
||||||
String code = nextCode.getCode();
|
|
||||||
|
|
||||||
if (isNotBlank(theCode)) {
|
|
||||||
if (theCode.equals(code) && (isBlank(theSystem) || theSystem.equals(system))) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else if (theCoding != null) {
|
|
||||||
if (StringUtils.equals(system, theCoding.getSystem()) && StringUtils.equals(code, theCoding.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (CodingDt next : theCodeableConcept.getCoding()) {
|
|
||||||
if (StringUtils.equals(system, next.getSystem()) && StringUtils.equals(code, next.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean multiXor(boolean... theValues) {
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < theValues.length; i++) {
|
|
||||||
if (theValues[i]) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count == 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
|
@ -29,14 +30,12 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
import org.hl7.fhir.dstu3.model.Coding;
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
@ -50,15 +49,14 @@ import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoValueSetR4.validateHaveExpansionOrThrowInternalErrorException;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoValueSetR4.validateHaveExpansionOrThrowInternalErrorException;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
@ -81,7 +79,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
super.start();
|
super.start();
|
||||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class,"myJpaValidationSupportChain" );
|
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class, "myJpaValidationSupportChain");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -264,108 +262,10 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
|
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||||
List<IIdType> valueSetIds = Collections.emptyList();
|
|
||||||
|
|
||||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
|
||||||
boolean haveCoding = theCoding != null && theCoding.isEmpty() == false;
|
|
||||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
|
||||||
|
|
||||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
|
||||||
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
|
||||||
}
|
|
||||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
|
||||||
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean haveIdentifierParam = theValueSetIdentifier != null && theValueSetIdentifier.isEmpty() == false;
|
|
||||||
ValueSet vs = null;
|
|
||||||
boolean isBuiltInValueSet = false;
|
|
||||||
if (theId != null) {
|
|
||||||
vs = read(theId, theRequestDetails);
|
|
||||||
} else if (haveIdentifierParam) {
|
|
||||||
vs = (ValueSet) myDefaultProfileValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
vs = (ValueSet) myValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
throw new InvalidRequestException("Unknown ValueSet identifier: " + theValueSetIdentifier.getValue());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
isBuiltInValueSet = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (theCode == null || theCode.isEmpty()) {
|
|
||||||
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
|
||||||
}
|
|
||||||
// String code = theCode.getValue();
|
|
||||||
// String system = toStringOrNull(theSystem);
|
|
||||||
IValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
|
||||||
if (result != null && result.isFound()) {
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult retVal = new ValidateCodeResult(true, "Found code", result.getCodeDisplay());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vs != null) {
|
|
||||||
ValidateCodeResult result;
|
|
||||||
if (myDaoConfig.isPreExpandValueSets() && !isBuiltInValueSet && myTerminologySvc.isValueSetPreExpandedForCodeValidation(vs)) {
|
|
||||||
result = myTerminologySvc.validateCodeIsInPreExpandedValueSet(new ValidationOptions(), vs, toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
|
||||||
} else {
|
|
||||||
ValueSet expansion = doExpand(vs);
|
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
|
||||||
result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
|
||||||
}
|
|
||||||
if (result != null) {
|
|
||||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
|
||||||
if (!theDisplay.getValue().equals(result.getDisplay())) {
|
|
||||||
return new ValidateCodeResult(false, "Display for code does not match", result.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValidateCodeResult(false, "Code not found", null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
|
||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode,
|
|
||||||
Coding theCoding, CodeableConcept theCodeableConcept) {
|
|
||||||
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String system = nextCode.getSystem();
|
|
||||||
String code = nextCode.getCode();
|
|
||||||
|
|
||||||
if (isNotBlank(theCode)) {
|
|
||||||
if (theCode.equals(code) && (isBlank(theSystem) || theSystem.equals(system))) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else if (theCoding != null) {
|
|
||||||
if (StringUtils.equals(system, theCoding.getSystem()) && StringUtils.equals(code, theCoding.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (Coding next : theCodeableConcept.getCoding()) {
|
|
||||||
if (StringUtils.equals(system, next.getSystem()) && StringUtils.equals(code, next.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -395,4 +295,8 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ConceptValidationOptions vsValidateCodeOptions() {
|
||||||
|
return new ConceptValidationOptions().setValidateDisplay(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
@ -49,13 +48,13 @@ import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
|
||||||
import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent;
|
import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent;
|
||||||
import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
|
import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
|
||||||
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||||
|
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
@ -243,108 +242,11 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
|
|
||||||
List<IIdType> valueSetIds = Collections.emptyList();
|
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||||
|
|
||||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
|
||||||
boolean haveCoding = theCoding != null && !theCoding.isEmpty();
|
|
||||||
boolean haveCode = theCode != null && !theCode.isEmpty();
|
|
||||||
|
|
||||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
|
||||||
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
|
||||||
}
|
|
||||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
|
||||||
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean haveIdentifierParam = theValueSetIdentifier != null && !theValueSetIdentifier.isEmpty();
|
|
||||||
ValueSet vs = null;
|
|
||||||
boolean isBuiltInValueSet = false;
|
|
||||||
if (theId != null) {
|
|
||||||
vs = read(theId, theRequestDetails);
|
|
||||||
} else if (haveIdentifierParam) {
|
|
||||||
vs = (ValueSet) myDefaultProfileValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
vs = (ValueSet) myValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
throw new InvalidRequestException("Unknown ValueSet identifier: " + theValueSetIdentifier.getValue());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
isBuiltInValueSet = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (theCode == null || theCode.isEmpty()) {
|
|
||||||
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
|
||||||
}
|
|
||||||
// String code = theCode.getValue();
|
|
||||||
// String system = toStringOrNull(theSystem);
|
|
||||||
IValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
|
||||||
if (result.isFound()) {
|
|
||||||
ValidateCodeResult retVal = new ValidateCodeResult(true, "Found code", result.getCodeDisplay());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vs != null) {
|
|
||||||
ValidateCodeResult result;
|
|
||||||
if (myDaoConfig.isPreExpandValueSets() && !isBuiltInValueSet && myTerminologySvc.isValueSetPreExpandedForCodeValidation(vs)) {
|
|
||||||
result = myTerminologySvc.validateCodeIsInPreExpandedValueSet(new ValidationOptions(), vs, toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
|
||||||
} else {
|
|
||||||
ValueSet expansion = doExpand(vs);
|
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
|
||||||
result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
|
||||||
}
|
|
||||||
if (result != null) {
|
|
||||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
|
||||||
if (!theDisplay.getValue().equals(result.getDisplay())) {
|
|
||||||
return new ValidateCodeResult(false, "Display for code does not match", result.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValidateCodeResult(false, "Code not found", null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
|
||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode,
|
|
||||||
Coding theCoding, CodeableConcept theCodeableConcept) {
|
|
||||||
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
|
||||||
ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String system = nextCode.getSystem();
|
|
||||||
String code = nextCode.getCode();
|
|
||||||
|
|
||||||
if (isNotBlank(theCode)) {
|
|
||||||
if (theCode.equals(code) && (isBlank(theSystem) || theSystem.equals(system))) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else if (theCoding != null) {
|
|
||||||
if (StringUtils.equals(system, theCoding.getSystem()) && StringUtils.equals(code, theCoding.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (Coding next : theCodeableConcept.getCoding()) {
|
|
||||||
if (StringUtils.equals(system, next.getSystem()) && StringUtils.equals(code, next.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
|
@ -55,6 +56,8 @@ import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||||
|
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoValueSetR4.validateHaveExpansionOrThrowInternalErrorException;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoValueSetR4.validateHaveExpansionOrThrowInternalErrorException;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
@ -245,108 +248,10 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
|
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||||
List<IIdType> valueSetIds = Collections.emptyList();
|
|
||||||
|
|
||||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
|
||||||
boolean haveCoding = theCoding != null && theCoding.isEmpty() == false;
|
|
||||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
|
||||||
|
|
||||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
|
||||||
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
|
||||||
}
|
|
||||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
|
||||||
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean haveIdentifierParam = theValueSetIdentifier != null && theValueSetIdentifier.isEmpty() == false;
|
|
||||||
ValueSet vs = null;
|
|
||||||
boolean isBuiltInValueSet = false;
|
|
||||||
if (theId != null) {
|
|
||||||
vs = read(theId, theRequestDetails);
|
|
||||||
} else if (haveIdentifierParam) {
|
|
||||||
vs = (ValueSet) myDefaultProfileValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
vs = (ValueSet) myValidationSupport.fetchValueSet(theValueSetIdentifier.getValue());
|
|
||||||
if (vs == null) {
|
|
||||||
throw new InvalidRequestException("Unknown ValueSet identifier: " + theValueSetIdentifier.getValue());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
isBuiltInValueSet = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (theCode == null || theCode.isEmpty()) {
|
|
||||||
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
|
||||||
}
|
|
||||||
// String code = theCode.getValue();
|
|
||||||
// String system = toStringOrNull(theSystem);
|
|
||||||
IValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
|
||||||
if (result.isFound()) {
|
|
||||||
ValidateCodeResult retVal = new ValidateCodeResult(true, "Found code", result.getCodeDisplay());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vs != null) {
|
|
||||||
ValidateCodeResult result;
|
|
||||||
if (myDaoConfig.isPreExpandValueSets() && !isBuiltInValueSet && myTerminologySvc.isValueSetPreExpandedForCodeValidation(vs)) {
|
|
||||||
result = myTerminologySvc.validateCodeIsInPreExpandedValueSet(new ValidationOptions(), vs, toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
|
||||||
} else {
|
|
||||||
ValueSet expansion = doExpand(vs);
|
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
|
||||||
result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
|
||||||
}
|
|
||||||
if (result != null) {
|
|
||||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
|
||||||
if (!theDisplay.getValue().equals(result.getDisplay())) {
|
|
||||||
return new ValidateCodeResult(false, "Display for code does not match", result.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValidateCodeResult(false, "Code not found", null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
|
||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode,
|
|
||||||
Coding theCoding, CodeableConcept theCodeableConcept) {
|
|
||||||
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
|
||||||
ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String system = nextCode.getSystem();
|
|
||||||
String code = nextCode.getCode();
|
|
||||||
|
|
||||||
if (isNotBlank(theCode)) {
|
|
||||||
if (theCode.equals(code) && (isBlank(theSystem) || theSystem.equals(system))) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else if (theCoding != null) {
|
|
||||||
if (StringUtils.equals(system, theCoding.getSystem()) && StringUtils.equals(code, theCoding.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (Coding next : theCodeableConcept.getCoding()) {
|
|
||||||
if (StringUtils.equals(system, next.getSystem()) && StringUtils.equals(code, next.getCode())) {
|
|
||||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.provider;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||||
|
@ -39,6 +40,8 @@ import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
@ -142,21 +145,27 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
return (Parameters) toValidateCodeResult(getContext(), result);
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanDt(result.isResult()));
|
|
||||||
if (isNotBlank(result.getMessage())) {
|
|
||||||
retVal.addParameter().setName("message").setValue(new StringDt(result.getMessage()));
|
|
||||||
}
|
|
||||||
if (isNotBlank(result.getDisplay())) {
|
|
||||||
retVal.addParameter().setName("display").setValue(new StringDt(result.getDisplay()));
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IBaseParameters toValidateCodeResult(FhirContext theContext, IValidationSupport.CodeValidationResult theResult) {
|
||||||
|
IBaseParameters retVal = ParametersUtil.newInstance(theContext);
|
||||||
|
|
||||||
|
ParametersUtil.addParameterToParametersBoolean(theContext, retVal, "result", theResult.isOk());
|
||||||
|
if (isNotBlank(theResult.getMessage())) {
|
||||||
|
ParametersUtil.addParameterToParametersString(theContext, retVal, "message", theResult.getMessage());
|
||||||
|
}
|
||||||
|
if (isNotBlank(theResult.getDisplay())) {
|
||||||
|
ParametersUtil.addParameterToParametersString(theContext, retVal, "display", theResult.getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
||||||
boolean haveOne = false;
|
boolean haveOne = false;
|
||||||
for (boolean next : theBooleans) {
|
for (boolean next : theBooleans) {
|
||||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
@ -148,16 +150,8 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(url, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
IValidationSupport.CodeValidationResult result = dao.validateCode(url, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
|
||||||
if (isNotBlank(result.getMessage())) {
|
|
||||||
retVal.addParameter().setName("message").setValue(new StringType(result.getMessage()));
|
|
||||||
}
|
|
||||||
if (isNotBlank(result.getDisplay())) {
|
|
||||||
retVal.addParameter().setName("display").setValue(new StringType(result.getDisplay()));
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.r4;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
@ -134,16 +136,8 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
|
||||||
if (isNotBlank(result.getMessage())) {
|
|
||||||
retVal.addParameter().setName("message").setValue(new StringType(result.getMessage()));
|
|
||||||
}
|
|
||||||
if (isNotBlank(result.getDisplay())) {
|
|
||||||
retVal.addParameter().setName("display").setValue(new StringType(result.getDisplay()));
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.r5;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
@ -134,16 +136,8 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
|
||||||
if (isNotBlank(result.getMessage())) {
|
|
||||||
retVal.addParameter().setName("message").setValue(new StringType(result.getMessage()));
|
|
||||||
}
|
|
||||||
if (isNotBlank(result.getDisplay())) {
|
|
||||||
retVal.addParameter().setName("display").setValue(new StringType(result.getDisplay()));
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IDao;
|
import ca.uhn.fhir.jpa.api.dao.IDao;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.api.model.TranslationQuery;
|
import ca.uhn.fhir.jpa.api.model.TranslationQuery;
|
||||||
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||||
|
@ -73,6 +72,7 @@ import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||||
|
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||||
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
|
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
|
@ -81,6 +81,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.util.ValidateUtil;
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
|
@ -105,10 +106,14 @@ import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.FullTextQuery;
|
import org.hibernate.search.jpa.FullTextQuery;
|
||||||
import org.hibernate.search.query.dsl.BooleanJunction;
|
import org.hibernate.search.query.dsl.BooleanJunction;
|
||||||
import org.hibernate.search.query.dsl.QueryBuilder;
|
import org.hibernate.search.query.dsl.QueryBuilder;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.r4.model.CanonicalType;
|
import org.hl7.fhir.r4.model.CanonicalType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
|
@ -169,6 +174,7 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
|
||||||
|
|
||||||
public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
public static final int DEFAULT_FETCH_SIZE = 250;
|
public static final int DEFAULT_FETCH_SIZE = 250;
|
||||||
|
@ -653,7 +659,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
includedConcepts = theIncludeOrExclude
|
includedConcepts = theIncludeOrExclude
|
||||||
.getConcept()
|
.getConcept()
|
||||||
.stream()
|
.stream()
|
||||||
.map(t->new VersionIndependentConcept(theIncludeOrExclude.getSystem(), t.getCode()))
|
.map(t -> new VersionIndependentConcept(theIncludeOrExclude.getSystem(), t.getCode()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +671,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
nextSystem = system;
|
nextSystem = system;
|
||||||
}
|
}
|
||||||
|
|
||||||
LookupCodeResult lookup = myValidationSupport.lookupCode(new ValidationSupportContext(myValidationSupport), nextSystem, next.getCode());
|
LookupCodeResult lookup = myValidationSupport.lookupCode(new ValidationSupportContext(provideValidationSupport()), nextSystem, next.getCode());
|
||||||
if (lookup != null && lookup.isFound()) {
|
if (lookup != null && lookup.isFound()) {
|
||||||
addOrRemoveCode(theValueSetCodeAccumulator, theAddedCodes, theAdd, nextSystem, next.getCode(), lookup.getCodeDisplay());
|
addOrRemoveCode(theValueSetCodeAccumulator, theAddedCodes, theAdd, nextSystem, next.getCode(), lookup.getCodeDisplay());
|
||||||
foundCount++;
|
foundCount++;
|
||||||
|
@ -1249,8 +1255,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(
|
protected IValidationSupport.CodeValidationResult validateCodeIsInPreExpandedValueSet(
|
||||||
ValidationOptions theValidationOptions,
|
ConceptValidationOptions theValidationOptions,
|
||||||
ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) {
|
ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||||
|
|
||||||
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet.hasId(), "ValueSet.id is required");
|
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet.hasId(), "ValueSet.id is required");
|
||||||
|
@ -1258,7 +1264,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
|
|
||||||
List<TermValueSetConcept> concepts = new ArrayList<>();
|
List<TermValueSetConcept> concepts = new ArrayList<>();
|
||||||
if (isNotBlank(theCode)) {
|
if (isNotBlank(theCode)) {
|
||||||
if (theValidationOptions.isGuessSystem()) {
|
if (theValidationOptions.isInferSystem()) {
|
||||||
concepts.addAll(myValueSetConceptDao.findByValueSetResourcePidAndCode(valueSetResourcePid.getIdAsLong(), theCode));
|
concepts.addAll(myValueSetConceptDao.findByValueSetResourcePidAndCode(valueSetResourcePid.getIdAsLong(), theCode));
|
||||||
} else if (isNotBlank(theSystem)) {
|
} else if (isNotBlank(theSystem)) {
|
||||||
concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theSystem, theCode));
|
concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theSystem, theCode));
|
||||||
|
@ -1276,19 +1282,40 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TermValueSetConcept concept : concepts) {
|
if (theValidationOptions.isValidateDisplay() && concepts.size() > 0) {
|
||||||
if (isNotBlank(theDisplay) && theDisplay.equals(concept.getDisplay())) {
|
for (TermValueSetConcept concept : concepts) {
|
||||||
return new IFhirResourceDaoValueSet.ValidateCodeResult(true, "Validation succeeded", concept.getDisplay());
|
if (isBlank(theDisplay) || isBlank(concept.getDisplay()) || theDisplay.equals(concept.getDisplay())) {
|
||||||
|
return new IValidationSupport.CodeValidationResult()
|
||||||
|
.setCode(concept.getCode())
|
||||||
|
.setDisplay(concept.getDisplay());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return createFailureCodeValidationResult(theSystem, theCode, " - Concept Display \"" + theDisplay + "\" does not match expected \"" + concepts.get(0).getDisplay() + "\"").setDisplay(concepts.get(0).getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!concepts.isEmpty()) {
|
if (!concepts.isEmpty()) {
|
||||||
return new IFhirResourceDaoValueSet.ValidateCodeResult(true, "Validation succeeded", concepts.get(0).getDisplay());
|
return new IValidationSupport.CodeValidationResult()
|
||||||
|
.setCode(concepts.get(0).getCode())
|
||||||
|
.setDisplay(concepts.get(0).getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return createFailureCodeValidationResult(theSystem, theCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeValidationResult createFailureCodeValidationResult(String theSystem, String theCode) {
|
||||||
|
String append = "";
|
||||||
|
return createFailureCodeValidationResult(theSystem, theCode, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeValidationResult createFailureCodeValidationResult(String theSystem, String theCode, String theAppend) {
|
||||||
|
return new CodeValidationResult()
|
||||||
|
.setSeverity(IssueSeverity.ERROR)
|
||||||
|
.setMessage("Unknown code {" + theSystem + "}" + theCode + theAppend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TermValueSetConcept> findByValueSetResourcePidSystemAndCode(ResourcePersistentId theResourcePid, String theSystem, String theCode) {
|
private List<TermValueSetConcept> findByValueSetResourcePidSystemAndCode(ResourcePersistentId theResourcePid, String theSystem, String theCode) {
|
||||||
|
@ -1659,6 +1686,58 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeValidationResult validateCode(ConceptValidationOptions theOptions, IIdType theValueSetId, String theValueSetUrl, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||||
|
|
||||||
|
CodeableConcept codeableConcept = toCanonicalCodeableConcept(theCodeableConcept);
|
||||||
|
boolean haveCodeableConcept = codeableConcept != null && codeableConcept.getCoding().size() > 0;
|
||||||
|
|
||||||
|
Coding coding = toCanonicalCoding(theCoding);
|
||||||
|
boolean haveCoding = coding != null && coding.isEmpty() == false;
|
||||||
|
|
||||||
|
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||||
|
|
||||||
|
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||||
|
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
||||||
|
}
|
||||||
|
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
||||||
|
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean haveIdentifierParam = isNotBlank(theValueSetUrl);
|
||||||
|
String valueSetUrl;
|
||||||
|
if (theValueSetId != null) {
|
||||||
|
IBaseResource valueSet = myDaoRegistry.getResourceDao("ValueSet").read(theValueSetId);
|
||||||
|
valueSetUrl = CommonCodeSystemsTerminologyService.getValueSetUrl(valueSet);
|
||||||
|
} else if (haveIdentifierParam) {
|
||||||
|
valueSetUrl = theValueSetUrl;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidationSupportContext validationContext = new ValidationSupportContext(provideValidationSupport());
|
||||||
|
|
||||||
|
String code = theCode;
|
||||||
|
String system = theSystem;
|
||||||
|
String display = theDisplay;
|
||||||
|
|
||||||
|
if (haveCodeableConcept) {
|
||||||
|
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||||
|
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||||
|
CodeValidationResult nextValidation = validateCode(validationContext, theOptions, nextCoding.getSystem(), nextCoding.getCode(), nextCoding.getDisplay(), valueSetUrl);
|
||||||
|
if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) {
|
||||||
|
return nextValidation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (haveCoding) {
|
||||||
|
system = coding.getSystem();
|
||||||
|
code = coding.getCode();
|
||||||
|
display = coding.getDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return validateCode(validationContext, theOptions, system, code, display, valueSetUrl);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isNotSafeToPreExpandValueSets() {
|
private boolean isNotSafeToPreExpandValueSets() {
|
||||||
return myDeferredStorageSvc != null && !myDeferredStorageSvc.isStorageQueueEmpty();
|
return myDeferredStorageSvc != null && !myDeferredStorageSvc.isStorageQueueEmpty();
|
||||||
}
|
}
|
||||||
|
@ -2020,7 +2099,36 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<VersionIndependentConcept> validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theValidationOptions, String theValueSetUrl, String theCodeSystem, String theCode) {
|
|
||||||
|
@CoverageIgnore
|
||||||
|
@Override
|
||||||
|
public IValidationSupport.CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
||||||
|
invokeRunnableForUnitTest();
|
||||||
|
|
||||||
|
if (isNotBlank(theValueSetUrl)) {
|
||||||
|
return validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystem, theCode, theDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||||
|
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||||
|
Optional<VersionIndependentConcept> codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
||||||
|
|
||||||
|
if (codeOpt != null && codeOpt.isPresent()) {
|
||||||
|
VersionIndependentConcept code = codeOpt.get();
|
||||||
|
if (!theOptions.isValidateDisplay() || (isNotBlank(code.getDisplay()) && isNotBlank(theDisplay) && code.getDisplay().equals(theDisplay))) {
|
||||||
|
return new CodeValidationResult()
|
||||||
|
.setCode(code.getCode())
|
||||||
|
.setDisplay(code.getDisplay());
|
||||||
|
} else {
|
||||||
|
return createFailureCodeValidationResult(theCodeSystem, theCode, " - Concept Display \"" + code.getDisplay() + "\" does not match expected \"" + code.getDisplay() + "\"").setDisplay(code.getDisplay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createFailureCodeValidationResult(theCodeSystem, theCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IValidationSupport.CodeValidationResult validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theValidationOptions, String theValueSetUrl, String theCodeSystem, String theCode, String theDisplay) {
|
||||||
IBaseResource valueSet = theValidationSupportContext.getRootValidationSupport().fetchValueSet(theValueSetUrl);
|
IBaseResource valueSet = theValidationSupportContext.getRootValidationSupport().fetchValueSet(theValueSetUrl);
|
||||||
|
|
||||||
// If we don't have a PID, this came from some source other than the JPA
|
// If we don't have a PID, this came from some source other than the JPA
|
||||||
|
@ -2029,24 +2137,26 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
Long pid = IDao.RESOURCE_PID.get((IAnyResource) valueSet);
|
Long pid = IDao.RESOURCE_PID.get((IAnyResource) valueSet);
|
||||||
if (pid != null) {
|
if (pid != null) {
|
||||||
if (isValueSetPreExpandedForCodeValidation(valueSet)) {
|
if (isValueSetPreExpandedForCodeValidation(valueSet)) {
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult outcome = validateCodeIsInPreExpandedValueSet(new ValidationOptions(), valueSet, theCodeSystem, theCode, null, null, null);
|
return validateCodeIsInPreExpandedValueSet(theValidationOptions, valueSet, theCodeSystem, theCode, null, null, null);
|
||||||
if (outcome != null && outcome.isResult()) {
|
|
||||||
return Optional.of(new VersionIndependentConcept(theCodeSystem, theCode));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueSet canonicalValueSet = toCanonicalValueSet(valueSet);
|
CodeValidationResult retVal = null;
|
||||||
VersionIndependentConcept wantConcept = new VersionIndependentConcept(theCodeSystem, theCode);
|
if (valueSet != null) {
|
||||||
ValueSetExpansionOptions expansionOptions = new ValueSetExpansionOptions()
|
retVal = new InMemoryTerminologyServerValidationSupport(myContext).validateCodeInValueSet(theValidationSupportContext, theValidationOptions, theCodeSystem, theCode, theDisplay, valueSet);
|
||||||
.setFailOnMissingCodeSystem(false);
|
} else {
|
||||||
|
String append = " - Unable to locate ValueSet[" + theValueSetUrl + "]";
|
||||||
|
retVal = createFailureCodeValidationResult(theCodeSystem, theCode, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retVal == null) {
|
||||||
|
String append = " - Unable to expand ValueSet[" + theValueSetUrl + "]";
|
||||||
|
retVal = createFailureCodeValidationResult(theCodeSystem, theCode, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
|
||||||
List<VersionIndependentConcept> expansionOutcome = expandValueSetAndReturnVersionIndependentConcepts(expansionOptions, canonicalValueSet, wantConcept);
|
|
||||||
return expansionOutcome
|
|
||||||
.stream()
|
|
||||||
.filter(t -> (theValidationOptions.isInferSystem() || t.getSystem().equals(theCodeSystem)) && t.getCode().equals(theCode))
|
|
||||||
.findFirst();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2171,6 +2281,12 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected abstract Coding toCanonicalCoding(@Nullable IBaseDatatype theCoding);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected abstract CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept);
|
||||||
|
|
||||||
public static class Job implements HapiJob {
|
public static class Job implements HapiJob {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ITermReadSvc myTerminologySvc;
|
private ITermReadSvc myTerminologySvc;
|
||||||
|
|
|
@ -20,18 +20,23 @@ package ca.uhn.fhir.jpa.term;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -132,8 +137,34 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(ValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
protected Coding toCanonicalCoding(@Nullable IBaseDatatype theCoding) {
|
||||||
|
Coding retVal = null;
|
||||||
|
if (theCoding != null) {
|
||||||
|
CodingDt coding = (CodingDt) theCoding;
|
||||||
|
retVal = new Coding(coding.getSystem(), coding.getCode(), coding.getDisplay());
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept) {
|
||||||
|
CodeableConcept outcome = null;
|
||||||
|
if (theCodeableConcept != null) {
|
||||||
|
outcome = new CodeableConcept();
|
||||||
|
CodeableConceptDt cc = (CodeableConceptDt) theCodeableConcept;
|
||||||
|
outcome.setText(cc.getText());
|
||||||
|
for (CodingDt next : cc.getCoding()) {
|
||||||
|
outcome.addCoding(toCanonicalCoding(next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeValidationResult validateCodeIsInPreExpandedValueSet(ConceptValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.ValidateUtil;
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||||
|
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||||
|
import org.hl7.fhir.convertors.VersionConvertor_40_50;
|
||||||
import org.hl7.fhir.convertors.conv30_40.CodeSystem30_40;
|
import org.hl7.fhir.convertors.conv30_40.CodeSystem30_40;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
|
@ -26,6 +28,7 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
@ -103,6 +106,20 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
||||||
return CodeSystem30_40.convertCodeSystem((CodeSystem)theCodeSystem);
|
return CodeSystem30_40.convertCodeSystem((CodeSystem)theCodeSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected org.hl7.fhir.r4.model.Coding toCanonicalCoding(IBaseDatatype theCoding) {
|
||||||
|
return VersionConvertor_30_40.convertCoding((org.hl7.fhir.dstu3.model.Coding) theCoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) {
|
||||||
|
return VersionConvertor_30_40.convertCodeableConcept((org.hl7.fhir.dstu3.model.CodeableConcept) theCoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void expandValueSet(ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator) {
|
public void expandValueSet(ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator) {
|
||||||
ValueSet valueSetToExpand = (ValueSet) theValueSetToExpand;
|
ValueSet valueSetToExpand = (ValueSet) theValueSetToExpand;
|
||||||
|
@ -130,35 +147,6 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
||||||
return valueSetR4;
|
return valueSetR4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CoverageIgnore
|
|
||||||
@Override
|
|
||||||
public IValidationSupport.CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
|
||||||
Optional<VersionIndependentConcept> codeOpt = Optional.empty();
|
|
||||||
boolean haveValidated = false;
|
|
||||||
|
|
||||||
if (isNotBlank(theValueSetUrl)) {
|
|
||||||
codeOpt = super.validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystem, theCode);
|
|
||||||
haveValidated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveValidated) {
|
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
|
||||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
|
||||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codeOpt != null && codeOpt.isPresent()) {
|
|
||||||
VersionIndependentConcept code = codeOpt.get();
|
|
||||||
IValidationSupport.CodeValidationResult retVal = new IValidationSupport.CodeValidationResult()
|
|
||||||
.setCode(code.getCode());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IValidationSupport.CodeValidationResult()
|
|
||||||
.setSeverity(IssueSeverity.ERROR)
|
|
||||||
.setMessage("Unknown code {" + theCodeSystem + "}" + theCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
||||||
return super.lookupCode(theSystem, theCode);
|
return super.lookupCode(theSystem, theCode);
|
||||||
|
@ -170,7 +158,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(ValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
public IValidationSupport.CodeValidationResult validateCodeIsInPreExpandedValueSet(ConceptValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||||
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
|
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
|
||||||
ValueSet valueSet = (ValueSet) theValueSet;
|
ValueSet valueSet = (ValueSet) theValueSet;
|
||||||
org.hl7.fhir.r4.model.ValueSet valueSetR4 = convertValueSet(valueSet);
|
org.hl7.fhir.r4.model.ValueSet valueSetR4 = convertValueSet(valueSet);
|
||||||
|
|
|
@ -5,28 +5,19 @@ import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
|
||||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import javax.transaction.Transactional;
|
import javax.transaction.Transactional;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -98,50 +89,29 @@ public class TermReadSvcR4 extends BaseTermReadSvcImpl implements ITermReadSvcR4
|
||||||
return (CodeSystem) theCodeSystem;
|
return (CodeSystem) theCodeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CoverageIgnore
|
|
||||||
@Override
|
|
||||||
public IValidationSupport.CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
|
||||||
invokeRunnableForUnitTest();
|
|
||||||
|
|
||||||
Optional<VersionIndependentConcept> codeOpt = Optional.empty();
|
|
||||||
boolean haveValidated = false;
|
|
||||||
|
|
||||||
if (isNotBlank(theValueSetUrl)) {
|
|
||||||
codeOpt = super.validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystem, theCode);
|
|
||||||
haveValidated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveValidated) {
|
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
|
||||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
|
||||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codeOpt != null && codeOpt.isPresent()) {
|
|
||||||
VersionIndependentConcept code = codeOpt.get();
|
|
||||||
IValidationSupport.CodeValidationResult retVal = new IValidationSupport.CodeValidationResult()
|
|
||||||
.setCode(code.getCode());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IValidationSupport.CodeValidationResult()
|
|
||||||
.setSeverity(IssueSeverity.ERROR)
|
|
||||||
.setMessage("Unknown code {" + theCodeSystem + "}" + theCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
||||||
return super.lookupCode(theSystem, theCode);
|
return super.lookupCode(theSystem, theCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(ValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
public IValidationSupport.CodeValidationResult validateCodeIsInPreExpandedValueSet(ConceptValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||||
ValueSet valueSet = (ValueSet) theValueSet;
|
ValueSet valueSet = (ValueSet) theValueSet;
|
||||||
Coding coding = (Coding) theCoding;
|
Coding coding = toCanonicalCoding(theCoding);
|
||||||
CodeableConcept codeableConcept = (CodeableConcept) theCodeableConcept;
|
CodeableConcept codeableConcept = toCanonicalCodeableConcept(theCodeableConcept);
|
||||||
return super.validateCodeIsInPreExpandedValueSet(theOptions, valueSet, theSystem, theCode, theDisplay, coding, codeableConcept);
|
return super.validateCodeIsInPreExpandedValueSet(theOptions, valueSet, theSystem, theCode, theDisplay, coding, codeableConcept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Coding toCanonicalCoding(IBaseDatatype theCoding) {
|
||||||
|
return (Coding) theCoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCodeableConcept) {
|
||||||
|
return (CodeableConcept) theCodeableConcept;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet) {
|
public boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet) {
|
||||||
ValueSet valueSet = (ValueSet) theValueSet;
|
ValueSet valueSet = (ValueSet) theValueSet;
|
||||||
|
|
|
@ -6,17 +6,15 @@ import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR5;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR5;
|
||||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||||
import ca.uhn.fhir.util.ValidateUtil;
|
import ca.uhn.fhir.util.ValidateUtil;
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
import org.hl7.fhir.convertors.VersionConvertor_40_50;
|
||||||
import org.hl7.fhir.convertors.conv40_50.CodeSystem40_50;
|
import org.hl7.fhir.convertors.conv40_50.CodeSystem40_50;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
|
||||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
@ -24,13 +22,9 @@ import org.hl7.fhir.utilities.TerminologyServiceOptions;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.transaction.Transactional;
|
import javax.transaction.Transactional;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -86,57 +80,18 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
|
||||||
return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR5);
|
return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IValidationSupport.CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
|
||||||
Optional<VersionIndependentConcept> codeOpt = Optional.empty();
|
|
||||||
boolean haveValidated = false;
|
|
||||||
|
|
||||||
if (isNotBlank(theValueSetUrl)) {
|
|
||||||
codeOpt = super.validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystem, theCode);
|
|
||||||
haveValidated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveValidated) {
|
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
|
||||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
|
||||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codeOpt != null && codeOpt.isPresent()) {
|
|
||||||
VersionIndependentConcept code = codeOpt.get();
|
|
||||||
ConceptDefinitionComponent def = new ConceptDefinitionComponent();
|
|
||||||
def.setCode(code.getCode());
|
|
||||||
IValidationSupport.CodeValidationResult retVal = new IValidationSupport.CodeValidationResult()
|
|
||||||
.setCode(code.getCode());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IValidationSupport.CodeValidationResult()
|
|
||||||
.setSeverity(IssueSeverity.ERROR)
|
|
||||||
.setCode("Unknown code {" + theCodeSystem + "}" + theCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
|
||||||
return super.lookupCode(theSystem, theCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FhirContext getFhirContext() {
|
public FhirContext getFhirContext() {
|
||||||
return myContext;
|
return myContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(ValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
public CodeValidationResult validateCodeIsInPreExpandedValueSet(ConceptValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||||
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
|
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
|
||||||
ValueSet valueSet = (ValueSet) theValueSet;
|
ValueSet valueSet = (ValueSet) theValueSet;
|
||||||
org.hl7.fhir.r4.model.ValueSet valueSetR4 = toCanonicalValueSet(valueSet);
|
org.hl7.fhir.r4.model.ValueSet valueSetR4 = toCanonicalValueSet(valueSet);
|
||||||
|
|
||||||
Coding coding = (Coding) theCoding;
|
org.hl7.fhir.r4.model.Coding codingR4 = toCanonicalCoding(theCoding);
|
||||||
org.hl7.fhir.r4.model.Coding codingR4 = null;
|
|
||||||
if (coding != null) {
|
|
||||||
codingR4 = new org.hl7.fhir.r4.model.Coding(coding.getSystem(), coding.getCode(), coding.getDisplay());
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeableConcept codeableConcept = (CodeableConcept) theCodeableConcept;
|
CodeableConcept codeableConcept = (CodeableConcept) theCodeableConcept;
|
||||||
org.hl7.fhir.r4.model.CodeableConcept codeableConceptR4 = null;
|
org.hl7.fhir.r4.model.CodeableConcept codeableConceptR4 = null;
|
||||||
|
@ -147,9 +102,22 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.validateCodeIsInPreExpandedValueSet(new TerminologyServiceOptions(), valueSetR4, theSystem, theCode, theDisplay, codingR4, codeableConceptR4);
|
return super.validateCodeIsInPreExpandedValueSet(theOptions, valueSetR4, theSystem, theCode, theDisplay, codingR4, codeableConceptR4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected org.hl7.fhir.r4.model.Coding toCanonicalCoding(IBaseDatatype theCoding) {
|
||||||
|
return VersionConvertor_40_50.convertCoding((Coding) theCoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) {
|
||||||
|
return VersionConvertor_40_50.convertCodeableConcept((CodeableConcept) theCoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected org.hl7.fhir.r4.model.ValueSet toCanonicalValueSet(IBaseResource theValueSet) throws org.hl7.fhir.exceptions.FHIRException {
|
protected org.hl7.fhir.r4.model.ValueSet toCanonicalValueSet(IBaseResource theValueSet) throws org.hl7.fhir.exceptions.FHIRException {
|
||||||
return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet((ValueSet) theValueSet);
|
return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet((ValueSet) theValueSet);
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
package ca.uhn.fhir.jpa.term.api;
|
package ca.uhn.fhir.jpa.term.api;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
|
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
|
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.IValueSetConceptAccumulator;
|
import ca.uhn.fhir.jpa.term.IValueSetConceptAccumulator;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||||
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
import org.hl7.fhir.r4.model.ConceptMap;
|
import org.hl7.fhir.r4.model.ConceptMap;
|
||||||
|
@ -105,7 +108,12 @@ public interface ITermReadSvc extends IValidationSupport {
|
||||||
/**
|
/**
|
||||||
* Version independent
|
* Version independent
|
||||||
*/
|
*/
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(ValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
|
CodeValidationResult validateCode(ConceptValidationOptions theOptions, IIdType theValueSetId, String theValueSetUrl, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version independent
|
||||||
|
*/
|
||||||
|
CodeValidationResult validateCodeIsInPreExpandedValueSet(ConceptValidationOptions theOptions, IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
|
||||||
|
|
||||||
boolean isValueSetPreExpandedForCodeValidation(ValueSet theValueSet);
|
boolean isValueSetPreExpandedForCodeValidation(ValueSet theValueSet);
|
||||||
|
|
||||||
|
@ -114,5 +122,4 @@ public interface ITermReadSvc extends IValidationSupport {
|
||||||
*/
|
*/
|
||||||
boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet);
|
boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
||||||
|
|
||||||
retVal.setDriver(new org.h2.Driver());
|
retVal.setDriver(new org.h2.Driver());
|
||||||
retVal.setUrl("jdbc:h2:mem:testdb_r4");
|
retVal.setUrl("jdbc:h2:mem:testdb_r4");
|
||||||
retVal.setMaxWaitMillis(10000);
|
retVal.setMaxWaitMillis(30000);
|
||||||
retVal.setUsername("");
|
retVal.setUsername("");
|
||||||
retVal.setPassword("");
|
retVal.setPassword("");
|
||||||
retVal.setMaxTotal(ourMaxThreads);
|
retVal.setMaxTotal(ourMaxThreads);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu2;
|
package ca.uhn.fhir.jpa.dao.dstu2;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
|
@ -8,9 +8,7 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.model.primitive.UriDt;
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -40,30 +38,42 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
public void testValidateCodeOperationByCodeAndSystemBadCode() {
|
||||||
UriDt valueSetIdentifier = null;
|
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||||
IdDt id = null;
|
IdDt id = null;
|
||||||
CodeDt code = new CodeDt("8450-9-XXX");
|
CodeDt code = new CodeDt("8450-9-XXX");
|
||||||
UriDt system = new UriDt("http://loinc.org");
|
UriDt system = new UriDt("http://loinc.org");
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemGood() {
|
public void testValidateCodeOperationByCodeAndSystemBadSystem() {
|
||||||
UriDt valueSetIdentifier = null;
|
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||||
|
IdDt id = null;
|
||||||
|
CodeDt code = new CodeDt("8450-9-XXX");
|
||||||
|
UriDt system = new UriDt("http://zzz");
|
||||||
|
StringDt display = null;
|
||||||
|
CodingDt coding = null;
|
||||||
|
CodeableConceptDt codeableConcept = null;
|
||||||
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
|
assertFalse(result.isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeOperationByIdentifierCodeInCsButNotInVs() {
|
||||||
|
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||||
IdDt id = null;
|
IdDt id = null;
|
||||||
CodeDt code = new CodeDt("8450-9");
|
CodeDt code = new CodeDt("8450-9");
|
||||||
UriDt system = new UriDt("http://loinc.org");
|
UriDt system = new UriDt("http://loinc.org");
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertFalse(result.isOk());
|
||||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -75,8 +85,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,9 +99,10 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = new StringDt("Systolic blood pressure at First encounterXXXX");
|
StringDt display = new StringDt("Systolic blood pressure at First encounterXXXX");
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
assertEquals("Concept Display \"Systolic blood pressure at First encounterXXXX\" does not match expected \"Systolic blood pressure at First encounter\"", result.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -103,8 +114,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +128,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,8 +142,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
@ -62,7 +61,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
assertEquals(TermValueSetPreExpansionStatusEnum.NOT_EXPANDED, vsEntity.getExpansionStatus());
|
assertEquals(TermValueSetPreExpansionStatusEnum.NOT_EXPANDED, vsEntity.getExpansionStatus());
|
||||||
});
|
});
|
||||||
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult validationOutcome;
|
IValidationSupport.CodeValidationResult validationOutcome;
|
||||||
UriType vsIdentifier = new UriType("http://decor.nictiz.nl/fhir/ValueSet/2.16.840.1.113883.2.4.3.11.60.40.2.20.5.2--20171231000000");
|
UriType vsIdentifier = new UriType("http://decor.nictiz.nl/fhir/ValueSet/2.16.840.1.113883.2.4.3.11.60.40.2.20.5.2--20171231000000");
|
||||||
CodeType code = new CodeType();
|
CodeType code = new CodeType();
|
||||||
CodeType system = new CodeType("urn:iso:std:iso:3166");
|
CodeType system = new CodeType("urn:iso:std:iso:3166");
|
||||||
|
@ -70,12 +69,12 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
// Validate good
|
// Validate good
|
||||||
code.setValue("NL");
|
code.setValue("NL");
|
||||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||||
assertEquals(true, validationOutcome.isResult());
|
assertEquals(true, validationOutcome.isOk());
|
||||||
|
|
||||||
// Validate bad
|
// Validate bad
|
||||||
code.setValue("QQ");
|
code.setValue("QQ");
|
||||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||||
assertEquals(false, validationOutcome.isResult());
|
assertEquals(false, validationOutcome.isOk());
|
||||||
|
|
||||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
|
|
||||||
|
@ -87,12 +86,12 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
// Validate good
|
// Validate good
|
||||||
code.setValue("NL");
|
code.setValue("NL");
|
||||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||||
assertEquals(true, validationOutcome.isResult());
|
assertEquals(true, validationOutcome.isOk());
|
||||||
|
|
||||||
// Validate bad
|
// Validate bad
|
||||||
code.setValue("QQ");
|
code.setValue("QQ");
|
||||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||||
assertEquals(false, validationOutcome.isResult());
|
assertEquals(false, validationOutcome.isOk());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,33 +188,6 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
|
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
|
||||||
UriType valueSetIdentifier = null;
|
|
||||||
IdType id = null;
|
|
||||||
CodeType code = new CodeType("8450-9-XXX");
|
|
||||||
UriType system = new UriType("http://acme.org");
|
|
||||||
StringType display = null;
|
|
||||||
Coding coding = null;
|
|
||||||
CodeableConcept codeableConcept = null;
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
|
||||||
assertFalse(result.isResult());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateCodeOperationByCodeAndSystemGood() {
|
|
||||||
UriType valueSetIdentifier = null;
|
|
||||||
IdType id = null;
|
|
||||||
CodeType code = new CodeType("8450-9");
|
|
||||||
UriType system = new UriType("http://acme.org");
|
|
||||||
StringType display = null;
|
|
||||||
Coding coding = null;
|
|
||||||
CodeableConcept codeableConcept = null;
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
|
||||||
assertTrue(result.isResult());
|
|
||||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByIdentifierAndCodeAndSystem() {
|
public void testValidateCodeOperationByIdentifierAndCodeAndSystem() {
|
||||||
UriType valueSetIdentifier = new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
UriType valueSetIdentifier = new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||||
|
@ -225,8 +197,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +211,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,8 +225,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounter");
|
StringType display = new StringType("Systolic blood pressure at First encounter");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,8 +239,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +254,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,10 +267,10 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType vsIdentifier = new StringType("http://hl7.org/fhir/ValueSet/administrative-gender");
|
StringType vsIdentifier = new StringType("http://hl7.org/fhir/ValueSet/administrative-gender");
|
||||||
StringType code = new StringType("male");
|
StringType code = new StringType("male");
|
||||||
StringType system = new StringType("http://hl7.org/fhir/administrative-gender");
|
StringType system = new StringType("http://hl7.org/fhir/administrative-gender");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(vsIdentifier, null, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(vsIdentifier, null, code, system, display, coding, codeableConcept, mySrd);
|
||||||
|
|
||||||
ourLog.info(result.getMessage());
|
ourLog.info(result.getMessage());
|
||||||
assertTrue(result.isResult(), result.getMessage());
|
assertTrue(result.isOk(), result.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
|
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("ABC");
|
p.setId("ABC");
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
|
@ -130,7 +130,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
mySearchParamRegistry.forceRefresh();
|
mySearchParamRegistry.forceRefresh();
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setGender(Enumerations.AdministrativeGender.MALE);
|
p.setGender(Enumerations.AdministrativeGender.MALE);
|
||||||
p.addIdentifier().setValue("VAL" + i);
|
p.addIdentifier().setValue("VAL" + i);
|
||||||
|
@ -185,7 +185,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
});
|
});
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
// Submit an update
|
// Submit an update
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId(patientId);
|
p.setId(patientId);
|
||||||
|
@ -224,7 +224,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("ABC");
|
p.setId("ABC");
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
|
@ -260,7 +260,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
@Test
|
@Test
|
||||||
public void testNoRetryInterceptor() {
|
public void testNoRetryInterceptor() {
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("ABC");
|
p.setId("ABC");
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
|
@ -300,7 +300,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("ABC");
|
p.setId("ABC");
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
|
@ -345,7 +345,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
IIdType pId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
IIdType pId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
|
|
||||||
Parameters patch = new Parameters();
|
Parameters patch = new Parameters();
|
||||||
Parameters.ParametersParameterComponent operation = patch.addParameter();
|
Parameters.ParametersParameterComponent operation = patch.addParameter();
|
||||||
|
@ -382,7 +382,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
// Make sure we saved the object
|
// Make sure we saved the object
|
||||||
Patient patient = myPatientDao.read(pId);
|
Patient patient = myPatientDao.read(pId);
|
||||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient));
|
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient));
|
||||||
assertEquals("11", patient.getMeta().getVersionId());
|
assertEquals("6", patient.getMeta().getVersionId());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
||||||
when(srd.getInterceptorBroadcaster()).thenReturn(new InterceptorService());
|
when(srd.getInterceptorBroadcaster()).thenReturn(new InterceptorService());
|
||||||
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("ABC");
|
p.setId("ABC");
|
||||||
|
|
|
@ -9,7 +9,10 @@ import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
||||||
|
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcLoincTest;
|
||||||
|
import ca.uhn.fhir.jpa.term.ZipCollectionBuilder;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||||
|
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||||
|
@ -36,9 +39,11 @@ import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.r4.model.CanonicalType;
|
import org.hl7.fhir.r4.model.CanonicalType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.r4.model.CodeType;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.Condition;
|
import org.hl7.fhir.r4.model.Condition;
|
||||||
import org.hl7.fhir.r4.model.DateTimeType;
|
import org.hl7.fhir.r4.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.r4.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r4.model.Enumerations;
|
import org.hl7.fhir.r4.model.Enumerations;
|
||||||
import org.hl7.fhir.r4.model.Group;
|
import org.hl7.fhir.r4.model.Group;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
@ -49,11 +54,13 @@ import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
import org.hl7.fhir.r4.model.Organization;
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.r4.model.Practitioner;
|
import org.hl7.fhir.r4.model.Practitioner;
|
||||||
|
import org.hl7.fhir.r4.model.Quantity;
|
||||||
import org.hl7.fhir.r4.model.Questionnaire;
|
import org.hl7.fhir.r4.model.Questionnaire;
|
||||||
import org.hl7.fhir.r4.model.QuestionnaireResponse;
|
import org.hl7.fhir.r4.model.QuestionnaireResponse;
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r4.model.UriType;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.utils.IResourceValidator;
|
import org.hl7.fhir.r5.utils.IResourceValidator;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -73,6 +80,7 @@ import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -95,6 +103,105 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ValidationSettings myValidationSettings;
|
private ValidationSettings myValidationSettings;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInValueSetWithUnknownCodeSystem() {
|
||||||
|
myValidationSupport.fetchCodeSystem("http://not-exist"); // preload DefaultProfileValidationSupport
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
vs.setUrl("http://vs");
|
||||||
|
vs
|
||||||
|
.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem("http://cs")
|
||||||
|
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code1")))
|
||||||
|
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code2")));
|
||||||
|
myValueSetDao.create(vs);
|
||||||
|
|
||||||
|
StructureDefinition sd = new StructureDefinition();
|
||||||
|
sd.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setType("Observation");
|
||||||
|
sd.setUrl("http://sd");
|
||||||
|
sd.setBaseDefinition("http://hl7.org/fhir/StructureDefinition/Observation");
|
||||||
|
sd.getDifferential()
|
||||||
|
.addElement()
|
||||||
|
.setPath("Observation.value[x]")
|
||||||
|
.addType(new ElementDefinition.TypeRefComponent(new UriType("Quantity")))
|
||||||
|
.setBinding(new ElementDefinition.ElementDefinitionBindingComponent().setStrength(Enumerations.BindingStrength.REQUIRED).setValueSet("http://vs"))
|
||||||
|
.setId("Observation.value[x]");
|
||||||
|
myStructureDefinitionDao.create(sd);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.getMeta().addProfile("http://sd");
|
||||||
|
obs.getText().setDivAsString("<div>Hello</div>");
|
||||||
|
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
|
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||||
|
obs.getCode().setText("hello");
|
||||||
|
obs.setSubject(new Reference("Patient/123"));
|
||||||
|
obs.addPerformer(new Reference("Practitioner/123"));
|
||||||
|
obs.setEffective(DateTimeType.now());
|
||||||
|
obs.setStatus(ObservationStatus.FINAL);
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs);
|
||||||
|
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));
|
||||||
|
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics(), encode(oo));
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs);
|
||||||
|
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));
|
||||||
|
assertEquals("Could not confirm that the codes provided are in the value set http://vs, and a code from this value set is required", oo.getIssueFirstRep().getDiagnostics(), encode(oo));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateSnapshotOnStructureDefinitionWithNoBase() {
|
||||||
|
|
||||||
|
// No base populated here, which isn't valid
|
||||||
|
StructureDefinition sd = new StructureDefinition();
|
||||||
|
sd.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setUrl("http://sd");
|
||||||
|
sd.getDifferential()
|
||||||
|
.addElement()
|
||||||
|
.setPath("Observation.value[x]")
|
||||||
|
.addType(new ElementDefinition.TypeRefComponent(new UriType("string")))
|
||||||
|
.setId("Observation.value[x]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
myStructureDefinitionDao.generateSnapshot(sd, null, null, null);
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals("StructureDefinition[id=null, url=http://sd] has no base", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
myStructureDefinitionDao.create(sd);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.getMeta().addProfile("http://sd");
|
||||||
|
obs.getText().setDivAsString("<div>Hello</div>");
|
||||||
|
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
|
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||||
|
obs.getCode().setText("hello");
|
||||||
|
obs.setSubject(new Reference("Patient/123"));
|
||||||
|
obs.addPerformer(new Reference("Practitioner/123"));
|
||||||
|
obs.setEffective(DateTimeType.now());
|
||||||
|
obs.setStatus(ObservationStatus.FINAL);
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
try {
|
||||||
|
myObservationDao.validate(obs, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals("StructureDefinition[id=null, url=http://sd] has no base", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use a valueset that explicitly brings in some UCUM codes
|
* Use a valueset that explicitly brings in some UCUM codes
|
||||||
*/
|
*/
|
||||||
|
@ -591,16 +698,10 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
obs.getCode().getCodingFirstRep().setSystem("http://example.com/codesystem");
|
obs.getCode().getCodingFirstRep().setSystem("http://example.com/codesystem");
|
||||||
obs.getCode().getCodingFirstRep().setCode("foo-foo");
|
obs.getCode().getCodingFirstRep().setCode("foo-foo");
|
||||||
obs.getCode().getCodingFirstRep().setDisplay("Some Code");
|
obs.getCode().getCodingFirstRep().setDisplay("Some Code");
|
||||||
try {
|
outcome = (OperationOutcome) myObservationDao.validate(obs, null, null, null, ValidationModeEnum.CREATE, "http://example.com/structuredefinition", mySrd).getOperationOutcome();
|
||||||
outcome = (OperationOutcome) myObservationDao.validate(obs, null, null, null, ValidationModeEnum.CREATE, "http://example.com/structuredefinition", mySrd).getOperationOutcome();
|
ourLog.info("Outcome: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||||
ourLog.info("Outcome: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
assertEquals("Unknown code in fragment CodeSystem 'http://example.com/codesystem#foo-foo'", outcome.getIssueFirstRep().getDiagnostics());
|
||||||
fail();
|
assertEquals(OperationOutcome.IssueSeverity.WARNING, outcome.getIssueFirstRep().getSeverity());
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
|
||||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));
|
|
||||||
assertEquals("None of the codes provided are in the value set http://example.com/valueset (http://example.com/valueset), and a code from this value set is required) (codes = http://example.com/codesystem#foo-foo)", oo.getIssueFirstRep().getDiagnostics());
|
|
||||||
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssueFirstRep().getSeverity());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Correct codesystem, Code in codesystem
|
// Correct codesystem, Code in codesystem
|
||||||
obs.getCode().getCodingFirstRep().setSystem("http://example.com/codesystem");
|
obs.getCode().getCodingFirstRep().setSystem("http://example.com/codesystem");
|
||||||
|
@ -1500,4 +1601,20 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKnownCodeSystemUnknownValueSetUri() {
|
||||||
|
CodeSystem cs = new CodeSystem();
|
||||||
|
cs.setUrl(ITermLoaderSvc.LOINC_URI);
|
||||||
|
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||||
|
cs.addConcept().setCode("10013-1");
|
||||||
|
myCodeSystemDao.create(cs);
|
||||||
|
|
||||||
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(new UriType("http://fooVs"), null, new StringType("10013-1"), new StringType(ITermLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
||||||
|
|
||||||
|
assertFalse(result.isOk());
|
||||||
|
assertEquals("Unknown code {http://loinc.org}10013-1 - Unable to locate ValueSet[http://fooVs]", result.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
|
@ -15,7 +15,6 @@ import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
import org.hl7.fhir.r4.model.UriType;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -49,14 +48,14 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
public void before02() throws IOException {
|
public void before02() throws IOException {
|
||||||
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||||
myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
|
myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
CodeSystem upload2 = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
|
CodeSystem upload2 = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
|
||||||
myCodeSystemDao.create(upload2, mySrd).getId().toUnqualifiedVersionless();
|
myCodeSystemDao.create(upload2, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
public void testValidateCodeOperationNoValueSet() {
|
||||||
UriType valueSetIdentifier = null;
|
UriType valueSetIdentifier = null;
|
||||||
IdType id = null;
|
IdType id = null;
|
||||||
CodeType code = new CodeType("8450-9-XXX");
|
CodeType code = new CodeType("8450-9-XXX");
|
||||||
|
@ -64,22 +63,12 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
try {
|
||||||
assertFalse(result.isResult());
|
myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
}
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
@Test
|
assertEquals("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.", e.getMessage());
|
||||||
public void testValidateCodeOperationByCodeAndSystemGood() {
|
}
|
||||||
UriType valueSetIdentifier = null;
|
|
||||||
IdType id = null;
|
|
||||||
CodeType code = new CodeType("8450-9");
|
|
||||||
UriType system = new UriType("http://acme.org");
|
|
||||||
StringType display = null;
|
|
||||||
Coding coding = null;
|
|
||||||
CodeableConcept codeableConcept = null;
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
|
||||||
assertTrue(result.isResult());
|
|
||||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -91,8 +80,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +94,10 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
assertEquals("Concept Display \"Systolic blood pressure at First encounterXXXX\" does not match expected \"Systolic blood pressure at First encounter\"", result.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -119,8 +109,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounter");
|
StringType display = new StringType("Systolic blood pressure at First encounter");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,8 +124,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,18 +141,18 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
myTerminologyDeferredStorageSvc.saveDeferred();
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,8 +165,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,18 +181,18 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
myTerminologyDeferredStorageSvc.saveDeferred();
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,17 +203,17 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
|
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
|
||||||
assertThat(resp, containsString("<expansion>"));
|
assertThat(resp, containsString("<expansion>"));
|
||||||
assertThat(resp, containsString("<contains>"));
|
assertThat(resp, containsString("<contains>"));
|
||||||
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
|
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
|
||||||
assertThat(resp, containsString("<code value=\"8450-9\"/>"));
|
assertThat(resp, containsString("<code value=\"8450-9\"/>"));
|
||||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure--expiration\"/>"));
|
assertThat(resp, containsString("<display value=\"Systolic blood pressure--expiration\"/>"));
|
||||||
assertThat(resp, containsString("</contains>"));
|
assertThat(resp, containsString("</contains>"));
|
||||||
assertThat(resp, containsString("<contains>"));
|
assertThat(resp, containsString("<contains>"));
|
||||||
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
|
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
|
||||||
assertThat(resp, containsString("<code value=\"11378-7\"/>"));
|
assertThat(resp, containsString("<code value=\"11378-7\"/>"));
|
||||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||||
assertThat(resp, containsString("</contains>"));
|
assertThat(resp, containsString("</contains>"));
|
||||||
assertThat(resp, containsString("</expansion>"));
|
assertThat(resp, containsString("</expansion>"));
|
||||||
|
|
||||||
|
@ -236,12 +226,12 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
assertThat(resp, stringContainsInOrder(
|
assertThat(resp, stringContainsInOrder(
|
||||||
"<code value=\"11378-7\"/>",
|
"<code value=\"11378-7\"/>",
|
||||||
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandByValueSet_ExceedsMaxSize() {
|
public void testExpandByValueSet_ExceedsMaxSize() {
|
||||||
// Add a bunch of codes
|
// Add a bunch of codes
|
||||||
|
@ -265,7 +255,7 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
|
public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
|
||||||
IPrimitiveType<String> display = null;
|
IPrimitiveType<String> display = null;
|
||||||
|
@ -274,14 +264,14 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
||||||
StringType vsIdentifier = new StringType("http://hl7.org/fhir/ValueSet/administrative-gender");
|
StringType vsIdentifier = new StringType("http://hl7.org/fhir/ValueSet/administrative-gender");
|
||||||
StringType code = new StringType("male");
|
StringType code = new StringType("male");
|
||||||
StringType system = new StringType("http://hl7.org/fhir/administrative-gender");
|
StringType system = new StringType("http://hl7.org/fhir/administrative-gender");
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(vsIdentifier, null, code, system, display, coding, codeableConcept, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(vsIdentifier, null, code, system, display, coding, codeableConcept, mySrd);
|
||||||
|
|
||||||
ourLog.info(result.getMessage());
|
ourLog.info(result.getMessage());
|
||||||
assertTrue( result.isResult(), result.getMessage());
|
assertTrue(result.isOk(), result.getMessage());
|
||||||
assertEquals("Male", result.getDisplay());
|
assertEquals("Male", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,23 +45,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
|
||||||
.operation()
|
.operation()
|
||||||
.onInstance(myExtensionalVsId)
|
.onInstance(myExtensionalVsId)
|
||||||
.named("validate-code")
|
.named("validate-code")
|
||||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
.withParameter(Parameters.class, "code", new CodeDt("11378-7"))
|
||||||
.andParameter("system", new UriDt("http://loinc.org"))
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
|
||||||
ourLog.info(resp);
|
|
||||||
|
|
||||||
assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateCodeOperationByCodeAndSystemType() {
|
|
||||||
Parameters respParam = ourClient
|
|
||||||
.operation()
|
|
||||||
.onType(ValueSet.class)
|
|
||||||
.named("validate-code")
|
|
||||||
.withParameter(Parameters.class, "code", new CodeDt("8450-9"))
|
|
||||||
.andParameter("system", new UriDt("http://loinc.org"))
|
.andParameter("system", new UriDt("http://loinc.org"))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
|
@ -749,6 +749,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
.named("validate-code")
|
.named("validate-code")
|
||||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||||
.andParameter("system", new UriType("http://acme.org"))
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
|
.andParameter("url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||||
|
@ -780,11 +781,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
|
||||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -810,11 +808,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
|
||||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
|
|
|
@ -10,9 +10,9 @@ import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||||
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
@ -54,6 +54,7 @@ import java.util.Optional;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM;
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
@ -61,7 +62,6 @@ import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
@ -98,11 +98,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
private void persistCodeSystem(CodeSystem theCodeSystem) {
|
private void persistCodeSystem(CodeSystem theCodeSystem) {
|
||||||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||||
@Override
|
@Override
|
||||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
|
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
|
||||||
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
|
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
myCodeSystemDao.readEntity(myExtensionalCsId, null).getId();
|
myCodeSystemDao.readEntity(myExtensionalCsId, null).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
createLocalVsWithUnknownCode(codeSystem);
|
createLocalVsWithUnknownCode(codeSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLocalCsAndVs() {
|
private void createLocalCs() {
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
@ -671,8 +671,8 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
.named("$expand")
|
.named("$expand")
|
||||||
.withNoParameters(Parameters.class)
|
.withNoParameters(Parameters.class)
|
||||||
.returnResourceType(ValueSet.class)
|
.returnResourceType(ValueSet.class)
|
||||||
.execute();
|
.execute();
|
||||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||||
|
|
||||||
// Update the CodeSystem URL and Codes
|
// Update the CodeSystem URL and Codes
|
||||||
|
@ -696,12 +696,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
.withNoParameters(Parameters.class)
|
.withNoParameters(Parameters.class)
|
||||||
.returnResourceType(ValueSet.class)
|
.returnResourceType(ValueSet.class)
|
||||||
.execute();
|
.execute();
|
||||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #516
|
* #516
|
||||||
*/
|
*/
|
||||||
|
@ -796,7 +795,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||||
|
|
||||||
|
@ -814,7 +813,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||||
|
|
||||||
|
@ -906,10 +905,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
||||||
createLocalCsAndVs();
|
createLocalCs();
|
||||||
|
createLocalVsWithIncludeConcept();
|
||||||
|
|
||||||
String url = ourServerBase +
|
String url = ourServerBase +
|
||||||
"/ValueSet/$validate-code?system=" +
|
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||||
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||||
"&code=AA";
|
"&code=AA";
|
||||||
|
|
||||||
|
@ -926,7 +926,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException {
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException {
|
||||||
createLocalCsAndVs();
|
createLocalCs();
|
||||||
createLocalVsWithIncludeConcept();
|
createLocalVsWithIncludeConcept();
|
||||||
|
|
||||||
String url = ourServerBase +
|
String url = ourServerBase +
|
||||||
|
@ -953,7 +953,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
.onType(ValueSet.class)
|
.onInstance(myExtensionalVsId)
|
||||||
.named("validate-code")
|
.named("validate-code")
|
||||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||||
.andParameter("system", new UriType("http://acme.org"))
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
|
@ -965,6 +965,24 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeOperationNoValueSetProvided() throws Exception {
|
||||||
|
loadAndPersistCodeSystemAndValueSet();
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient
|
||||||
|
.operation()
|
||||||
|
.onType(ValueSet.class)
|
||||||
|
.named("validate-code")
|
||||||
|
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||||
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
|
.execute();
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("HTTP 400 Bad Request: Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeAgainstBuiltInSystem() {
|
public void testValidateCodeAgainstBuiltInSystem() {
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
|
@ -983,11 +1001,8 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("succeeded"));
|
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
|
||||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1018,7 +1033,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet validateCodeGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?code=ChildAA&_pretty=true");
|
HttpGet validateCodeGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=ChildAA&_pretty=true");
|
||||||
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet)) {
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet)) {
|
||||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
|
@ -1026,7 +1041,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
assertEquals(true, output.getParameterBool("result"));
|
assertEquals(true, output.getParameterBool("result"));
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet validateCodeGet2 = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?code=FOO&_pretty=true");
|
HttpGet validateCodeGet2 = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=FOO&_pretty=true");
|
||||||
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet2)) {
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet2)) {
|
||||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
|
@ -1070,7 +1085,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||||
cs.getConcepts().add(parentB);
|
cs.getConcepts().add(parentB);
|
||||||
|
|
||||||
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
|
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
|
||||||
return codeSystem;
|
return codeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||||
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
@ -53,6 +53,7 @@ import java.util.Optional;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM;
|
||||||
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET;
|
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
@ -60,7 +61,6 @@ import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
@ -983,8 +983,8 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
.named("$expand")
|
.named("$expand")
|
||||||
.withNoParameters(Parameters.class)
|
.withNoParameters(Parameters.class)
|
||||||
.returnResourceType(ValueSet.class)
|
.returnResourceType(ValueSet.class)
|
||||||
.execute();
|
.execute();
|
||||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||||
|
|
||||||
// Update the CodeSystem URL and Codes
|
// Update the CodeSystem URL and Codes
|
||||||
|
@ -1008,12 +1008,11 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
.withNoParameters(Parameters.class)
|
.withNoParameters(Parameters.class)
|
||||||
.returnResourceType(ValueSet.class)
|
.returnResourceType(ValueSet.class)
|
||||||
.execute();
|
.execute();
|
||||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #516
|
* #516
|
||||||
*/
|
*/
|
||||||
|
@ -1108,7 +1107,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||||
|
|
||||||
|
@ -1126,7 +1125,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||||
|
|
||||||
|
@ -1219,9 +1218,10 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
|
createLocalVsWithIncludeConcept();
|
||||||
|
|
||||||
String url = ourServerBase +
|
String url = ourServerBase +
|
||||||
"/ValueSet/$validate-code?system=" +
|
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||||
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||||
"&code=AA";
|
"&code=AA";
|
||||||
|
|
||||||
|
@ -1265,7 +1265,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
|
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
.operation()
|
.operation()
|
||||||
.onType(ValueSet.class)
|
.onInstance(myExtensionalVsId)
|
||||||
.named("validate-code")
|
.named("validate-code")
|
||||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||||
.andParameter("system", new UriType("http://acme.org"))
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
|
@ -1297,12 +1297,10 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("succeeded"));
|
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
|
||||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good code and system, but not in specified valueset
|
// Good code and system, but not in specified valueset
|
||||||
{
|
{
|
||||||
Parameters respParam = myClient
|
Parameters respParam = myClient
|
||||||
|
@ -1322,7 +1320,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
assertEquals(false, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||||
|
|
||||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("Code not found"));
|
assertEquals("Unknown code 'http://hl7.org/fhir/administrative-gender#male'", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,9 +1350,10 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
try (CloseableHttpResponse status = ourHttpClient.execute(expandGet)) {
|
try (CloseableHttpResponse status = ourHttpClient.execute(expandGet)) {
|
||||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
|
assertThat(response, containsString("<display value=\"Child AA\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet validateCodeGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?code=ChildAA&_pretty=true");
|
HttpGet validateCodeGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=ChildAA&_pretty=true");
|
||||||
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet)) {
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet)) {
|
||||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
|
@ -1362,7 +1361,32 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
assertEquals(true, output.getParameterBool("result"));
|
assertEquals(true, output.getParameterBool("result"));
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet validateCodeGet2 = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?code=FOO&_pretty=true");
|
HttpGet validateCodeGet2 = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=FOO&_pretty=true");
|
||||||
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet2)) {
|
||||||
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info("Response: {}", response);
|
||||||
|
Parameters output = myFhirCtx.newXmlParser().parseResource(Parameters.class, response);
|
||||||
|
assertEquals(false, output.getParameterBool("result"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now do a pre-expansion
|
||||||
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
|
|
||||||
|
expandGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$expand?_pretty=true");
|
||||||
|
try (CloseableHttpResponse status = ourHttpClient.execute(expandGet)) {
|
||||||
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info("Response: {}", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateCodeGet = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=ChildAA&_pretty=true");
|
||||||
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet)) {
|
||||||
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info("Response: {}", response);
|
||||||
|
Parameters output = myFhirCtx.newXmlParser().parseResource(Parameters.class, response);
|
||||||
|
assertEquals(true, output.getParameterBool("result"));
|
||||||
|
}
|
||||||
|
|
||||||
|
validateCodeGet2 = new HttpGet(ourServerBase + "/ValueSet/" + vsId.getIdPart() + "/$validate-code?system=http://mycs&code=FOO&_pretty=true");
|
||||||
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet2)) {
|
try (CloseableHttpResponse status = ourHttpClient.execute(validateCodeGet2)) {
|
||||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info("Response: {}", response);
|
ourLog.info("Response: {}", response);
|
||||||
|
@ -1407,7 +1431,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
||||||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||||
cs.getConcepts().add(parentB);
|
cs.getConcepts().add(parentB);
|
||||||
|
|
||||||
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
|
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
|
||||||
return codeSystem;
|
return codeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,8 @@ package ca.uhn.fhir.jpa.term;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
|
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.hl7.fhir.dstu3.model.CodeType;
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
import org.hl7.fhir.dstu3.model.Coding;
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
@ -13,10 +11,10 @@ import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.PrimitiveType;
|
import org.hl7.fhir.dstu3.model.PrimitiveType;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.Type;
|
import org.hl7.fhir.dstu3.model.Type;
|
||||||
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -30,12 +28,12 @@ import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
|
@ -228,11 +226,13 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||||
myLoader.loadLoinc(files.getFiles(), mySrd);
|
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||||
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(null, null, new StringType("10013-1"), new StringType(ITermLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(new UriType("http://loinc.org/vs"), null, new StringType("10013-1"), new StringType(ITermLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
||||||
|
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Found code", result.getMessage());
|
assertEquals("R' wave amplitude in lead I", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -240,11 +240,13 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||||
myLoader.loadLoinc(files.getFiles(), mySrd);
|
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||||
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
|
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||||
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(null, null, new StringType("10013-1-9999999999"), new StringType(ITermLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(new UriType("http://loinc.org/vs"), null, new StringType("10013-1-9999999999"), new StringType(ITermLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
||||||
|
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isOk());
|
||||||
assertEquals("Code not found", result.getMessage());
|
assertEquals("Unknown code {http://loinc.org}10013-1-9999999999 - Unable to expand ValueSet[http://loinc.org/vs]", result.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> toExpandedCodes(ValueSet theExpanded) {
|
private Set<String> toExpandedCodes(ValueSet theExpanded) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package ca.uhn.fhir.jpa.term;
|
||||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMap;
|
import ca.uhn.fhir.jpa.entity.TermConceptMap;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
|
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
|
||||||
|
@ -43,8 +42,8 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(TerminologySvcImplR4Test.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(TerminologySvcImplR4Test.class);
|
||||||
ValidationOptions optsNoGuess = new ValidationOptions();
|
ConceptValidationOptions optsNoGuess = new ConceptValidationOptions();
|
||||||
ValidationOptions optsGuess = new ValidationOptions().guessSystem();
|
ConceptValidationOptions optsGuess = new ConceptValidationOptions().setInferSystem(true);
|
||||||
private IIdType myConceptMapId;
|
private IIdType myConceptMapId;
|
||||||
|
|
||||||
private void createAndPersistConceptMap() {
|
private void createAndPersistConceptMap() {
|
||||||
|
@ -1799,42 +1798,37 @@ public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
||||||
|
|
||||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, null);
|
IValidationSupport.CodeValidationResult result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, null);
|
||||||
assertNull(result);
|
assertNull(result);
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "BOGUS", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "BOGUS", null, null, null);
|
||||||
assertNull(result);
|
assertFalse(result.isOk());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "11378-7", null, null, null);
|
||||||
assertNull(result);
|
assertFalse(result.isOk());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", "Systolic blood pressure at First encounter", null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", "Systolic blood pressure at First encounter", null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
Coding coding = new Coding("http://acme.org", "11378-7", "Systolic blood pressure at First encounter");
|
Coding coding = new Coding("http://acme.org", "11378-7", "Systolic blood pressure at First encounter");
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, coding, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, coding, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
||||||
codeableConcept.addCoding(coding);
|
codeableConcept.addCoding(coding);
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,43 +1846,38 @@ public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
||||||
|
|
||||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||||
|
|
||||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, null);
|
IValidationSupport.CodeValidationResult result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, null);
|
||||||
assertNull(result);
|
assertNull(result);
|
||||||
|
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "BOGUS", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "BOGUS", null, null, null);
|
||||||
assertNull(result);
|
assertFalse(result.isOk());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, "11378-7", null, null, null);
|
||||||
assertNull(result);
|
assertFalse(result.isOk());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", "Systolic blood pressure at First encounter", null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", "Systolic blood pressure at First encounter", null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
Coding coding = new Coding("http://acme.org", "11378-7", "Systolic blood pressure at First encounter");
|
Coding coding = new Coding("http://acme.org", "11378-7", "Systolic blood pressure at First encounter");
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, coding, null);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, coding, null);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
|
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
||||||
codeableConcept.addCoding(coding);
|
codeableConcept.addCoding(coding);
|
||||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isOk());
|
||||||
assertEquals("Validation succeeded", result.getMessage());
|
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
<code value="8450-9" />
|
<code value="8450-9" />
|
||||||
<display value="Systolic blood pressure--expiration" />
|
<display value="Systolic blood pressure--expiration" />
|
||||||
</concept>
|
</concept>
|
||||||
|
<concept>
|
||||||
|
<code value="11378-7" />
|
||||||
|
<display value="Systolic blood pressure at First encounter" />
|
||||||
|
</concept>
|
||||||
</codeSystem>
|
</codeSystem>
|
||||||
<compose>
|
<compose>
|
||||||
<include>
|
<include>
|
||||||
|
@ -124,4 +128,4 @@
|
||||||
</concept>
|
</concept>
|
||||||
</include>
|
</include>
|
||||||
</compose>
|
</compose>
|
||||||
</ValueSet>
|
</ValueSet>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.convertors.conv10_50.ValueSet10_50;
|
import org.hl7.fhir.convertors.conv10_50.ValueSet10_50;
|
||||||
|
@ -26,6 +27,8 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -90,8 +93,11 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
|
|
||||||
private org.hl7.fhir.r5.model.ValueSet expandValueSetToCanonical(ValidationSupportContext theValidationSupportContext, IBaseResource theValueSetToExpand, @Nullable String theWantSystem, @Nullable String theWantCode) {
|
private org.hl7.fhir.r5.model.ValueSet expandValueSetToCanonical(ValidationSupportContext theValidationSupportContext, IBaseResource theValueSetToExpand, @Nullable String theWantSystem, @Nullable String theWantCode) {
|
||||||
org.hl7.fhir.r5.model.ValueSet expansionR5;
|
org.hl7.fhir.r5.model.ValueSet expansionR5;
|
||||||
switch (myCtx.getVersion().getVersion()) {
|
switch (theValueSetToExpand.getStructureFhirVersionEnum()) {
|
||||||
case DSTU2:
|
case DSTU2: {
|
||||||
|
expansionR5 = expandValueSetDstu2(theValidationSupportContext, (ca.uhn.fhir.model.dstu2.resource.ValueSet) theValueSetToExpand, theWantSystem, theWantCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DSTU2_HL7ORG: {
|
case DSTU2_HL7ORG: {
|
||||||
expansionR5 = expandValueSetDstu2Hl7Org(theValidationSupportContext, (ValueSet) theValueSetToExpand, theWantSystem, theWantCode);
|
expansionR5 = expandValueSetDstu2Hl7Org(theValidationSupportContext, (ValueSet) theValueSetToExpand, theWantSystem, theWantCode);
|
||||||
break;
|
break;
|
||||||
|
@ -122,11 +128,11 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
@Override
|
@Override
|
||||||
public CodeValidationResult
|
public CodeValidationResult
|
||||||
validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, @Nonnull IBaseResource theValueSet) {
|
validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, @Nonnull IBaseResource theValueSet) {
|
||||||
org.hl7.fhir.r5.model.ValueSet expansion = expandValueSetToCanonical(theValidationSupportContext, theValueSet, theCodeSystem, theCode);
|
org.hl7.fhir.r5.model.ValueSet expansion = expandValueSetToCanonical(theValidationSupportContext, theValueSet, theCodeSystem, theCode);
|
||||||
if (expansion == null) {
|
if (expansion == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return validateCodeInExpandedValueSet(theValidationSupportContext, theOptions, theCodeSystem, theCode, expansion);
|
return validateCodeInExpandedValueSet(theValidationSupportContext, theOptions, theCodeSystem, theCode, theDisplay, expansion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,11 +180,11 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
|
|
||||||
IBaseResource expansion = valueSetExpansionOutcome.getValueSet();
|
IBaseResource expansion = valueSetExpansionOutcome.getValueSet();
|
||||||
|
|
||||||
return validateCodeInExpandedValueSet(theValidationSupportContext, theOptions, theCodeSystem, theCode, expansion);
|
return validateCodeInExpandedValueSet(theValidationSupportContext, theOptions, theCodeSystem, theCode, theDisplay, expansion);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodeValidationResult validateCodeInExpandedValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, IBaseResource theExpansion) {
|
private CodeValidationResult validateCodeInExpandedValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, IBaseResource theExpansion) {
|
||||||
assert theExpansion != null;
|
assert theExpansion != null;
|
||||||
|
|
||||||
boolean caseSensitive = true;
|
boolean caseSensitive = true;
|
||||||
|
@ -269,11 +275,20 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
}
|
}
|
||||||
if (codeMatches) {
|
if (codeMatches) {
|
||||||
if (theOptions.isInferSystem() || nextExpansionCode.getSystem().equals(theCodeSystem)) {
|
if (theOptions.isInferSystem() || nextExpansionCode.getSystem().equals(theCodeSystem)) {
|
||||||
return new CodeValidationResult()
|
if (!theOptions.isValidateDisplay() || (isBlank(nextExpansionCode.getDisplay()) || isBlank(theDisplay) || nextExpansionCode.getDisplay().equals(theDisplay))) {
|
||||||
.setCode(theCode)
|
return new CodeValidationResult()
|
||||||
.setDisplay(nextExpansionCode.getDisplay())
|
.setCode(theCode)
|
||||||
.setCodeSystemName(codeSystemName)
|
.setDisplay(nextExpansionCode.getDisplay())
|
||||||
.setCodeSystemVersion(codeSystemVersion);
|
.setCodeSystemName(codeSystemName)
|
||||||
|
.setCodeSystemVersion(codeSystemVersion);
|
||||||
|
} else {
|
||||||
|
return new CodeValidationResult()
|
||||||
|
.setSeverity(IssueSeverity.ERROR)
|
||||||
|
.setDisplay(nextExpansionCode.getDisplay())
|
||||||
|
.setMessage("Concept Display \"" + theDisplay + "\" does not match expected \"" + nextExpansionCode.getDisplay() + "\"")
|
||||||
|
.setCodeSystemName(codeSystemName)
|
||||||
|
.setCodeSystemVersion(codeSystemVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,6 +331,33 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
return (output);
|
return (output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private org.hl7.fhir.r5.model.ValueSet expandValueSetDstu2(ValidationSupportContext theValidationSupportContext, ca.uhn.fhir.model.dstu2.resource.ValueSet theInput, @Nullable String theWantSystem, @Nullable String theWantCode) {
|
||||||
|
IParser parserRi = FhirContext.forCached(FhirVersionEnum.DSTU2_HL7ORG).newJsonParser();
|
||||||
|
IParser parserHapi = FhirContext.forCached(FhirVersionEnum.DSTU2).newJsonParser();
|
||||||
|
|
||||||
|
Function<String, CodeSystem> codeSystemLoader = t -> {
|
||||||
|
// ca.uhn.fhir.model.dstu2.resource.ValueSet codeSystem = (ca.uhn.fhir.model.dstu2.resource.ValueSet) theValidationSupportContext.getRootValidationSupport().fetchCodeSystem(t);
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.ValueSet codeSystem = theInput;
|
||||||
|
CodeSystem retVal = null;
|
||||||
|
if (codeSystem != null) {
|
||||||
|
retVal = new CodeSystem();
|
||||||
|
retVal.setUrl(codeSystem.getUrl());
|
||||||
|
addCodesDstu2(codeSystem.getCodeSystem().getConcept(), retVal.getConcept());
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
};
|
||||||
|
Function<String, org.hl7.fhir.r5.model.ValueSet> valueSetLoader = t -> {
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.ValueSet valueSet = (ca.uhn.fhir.model.dstu2.resource.ValueSet) theValidationSupportContext.getRootValidationSupport().fetchValueSet(t);
|
||||||
|
org.hl7.fhir.dstu2.model.ValueSet valueSetRi = parserRi.parseResource(org.hl7.fhir.dstu2.model.ValueSet.class, parserHapi.encodeResourceToString(valueSet));
|
||||||
|
return ValueSet10_50.convertValueSet(valueSetRi);
|
||||||
|
};
|
||||||
|
|
||||||
|
org.hl7.fhir.dstu2.model.ValueSet valueSetRi = parserRi.parseResource(org.hl7.fhir.dstu2.model.ValueSet.class, parserHapi.encodeResourceToString(theInput));
|
||||||
|
org.hl7.fhir.r5.model.ValueSet input = ValueSet10_50.convertValueSet(valueSetRi);
|
||||||
|
org.hl7.fhir.r5.model.ValueSet output = expandValueSetR5(theValidationSupportContext, input, codeSystemLoader, valueSetLoader, theWantSystem, theWantCode);
|
||||||
|
return (output);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) {
|
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) {
|
||||||
|
@ -353,6 +395,14 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addCodesDstu2(List<ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept> theSourceList, List<CodeSystem.ConceptDefinitionComponent> theTargetList) {
|
||||||
|
for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept nextSource : theSourceList) {
|
||||||
|
CodeSystem.ConceptDefinitionComponent targetConcept = new CodeSystem.ConceptDefinitionComponent().setCode(nextSource.getCode()).setDisplay(nextSource.getDisplay());
|
||||||
|
theTargetList.add(targetConcept);
|
||||||
|
addCodesDstu2(nextSource.getConcept(), targetConcept.getConcept());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private org.hl7.fhir.r5.model.ValueSet expandValueSetDstu3(ValidationSupportContext theValidationSupportContext, org.hl7.fhir.dstu3.model.ValueSet theInput, @Nullable String theWantSystem, @Nullable String theWantCode) {
|
private org.hl7.fhir.r5.model.ValueSet expandValueSetDstu3(ValidationSupportContext theValidationSupportContext, org.hl7.fhir.dstu3.model.ValueSet theInput, @Nullable String theWantSystem, @Nullable String theWantCode) {
|
||||||
Function<String, org.hl7.fhir.r5.model.CodeSystem> codeSystemLoader = t -> {
|
Function<String, org.hl7.fhir.r5.model.CodeSystem> codeSystemLoader = t -> {
|
||||||
|
@ -452,6 +502,33 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
||||||
addCodes(system, codesList, nextCodeList, wantCodes);
|
addCodes(system, codesList, nextCodeList, wantCodes);
|
||||||
ableToHandleCode = true;
|
ableToHandleCode = true;
|
||||||
}
|
}
|
||||||
|
} else if (theComposeListIsInclude) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're doing an expansion specifically looking for a single code, that means we're validating that code.
|
||||||
|
* In the case where we have a ValueSet that explicitly enumerates a collection of codes
|
||||||
|
* (via ValueSet.compose.include.code) in a code system that is unknown we'll assume the code is valid
|
||||||
|
* even iof we can't find the CodeSystem. This is a compromise obviously, since it would be ideal for
|
||||||
|
* CodeSystems to always be known, but realistically there are always going to be CodeSystems that
|
||||||
|
* can't be supplied because of copyright issues, or because they are grammar based. Allowing a VS to
|
||||||
|
* enumerate a set of good codes for them is a nice compromise there.
|
||||||
|
*/
|
||||||
|
for (org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent next : theComposeList) {
|
||||||
|
if (Objects.equals(next.getSystem(), theWantSystem)) {
|
||||||
|
Optional<org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent> matchingEnumeratedConcept = next.getConcept().stream().filter(t -> Objects.equals(t.getCode(), theWantCode)).findFirst();
|
||||||
|
if (matchingEnumeratedConcept.isPresent()) {
|
||||||
|
CodeSystem.ConceptDefinitionComponent conceptDefinition = new CodeSystem.ConceptDefinitionComponent()
|
||||||
|
.addConcept()
|
||||||
|
.setCode(theWantCode)
|
||||||
|
.setDisplay(matchingEnumeratedConcept.get().getDisplay());
|
||||||
|
List<CodeSystem.ConceptDefinitionComponent> codesList = Collections.singletonList(conceptDefinition);
|
||||||
|
addCodes(system, codesList, nextCodeList, wantCodes);
|
||||||
|
ableToHandleCode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.hl7.fhir.common.hapi.validation.support;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
@ -18,6 +19,8 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple validation support module that handles profile snapshot generation.
|
* Simple validation support module that handles profile snapshot generation.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -75,9 +78,14 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
||||||
}
|
}
|
||||||
theValidationSupportContext.getCurrentlyGeneratingSnapshots().add(inputUrl);
|
theValidationSupportContext.getCurrentlyGeneratingSnapshots().add(inputUrl);
|
||||||
|
|
||||||
IBaseResource base = theValidationSupportContext.getRootValidationSupport().fetchStructureDefinition(inputCanonical.getBaseDefinition());
|
String baseDefinition = inputCanonical.getBaseDefinition();
|
||||||
|
if (isBlank(baseDefinition)) {
|
||||||
|
throw new PreconditionFailedException("StructureDefinition[id=" + inputCanonical.getIdElement().getId() + ", url=" + inputCanonical.getUrl() + "] has no base");
|
||||||
|
}
|
||||||
|
|
||||||
|
IBaseResource base = theValidationSupportContext.getRootValidationSupport().fetchStructureDefinition(baseDefinition);
|
||||||
if (base == null) {
|
if (base == null) {
|
||||||
throw new PreconditionFailedException("Unknown base definition: " + inputCanonical.getBaseDefinition());
|
throw new PreconditionFailedException("Unknown base definition: " + baseDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
org.hl7.fhir.r5.model.StructureDefinition baseCanonical = (org.hl7.fhir.r5.model.StructureDefinition) converter.toCanonical(base);
|
org.hl7.fhir.r5.model.StructureDefinition baseCanonical = (org.hl7.fhir.r5.model.StructureDefinition) converter.toCanonical(base);
|
||||||
|
@ -112,6 +120,8 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
||||||
|
|
||||||
return theInput;
|
return theInput;
|
||||||
|
|
||||||
|
} catch (BaseServerResponseException e) {
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new InternalErrorException("Failed to generate snapshot", e);
|
throw new InternalErrorException("Failed to generate snapshot", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package org.hl7.fhir.common.hapi.validation.support;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
|
import org.hl7.fhir.r4.model.CodeType;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class InMemoryTerminologyServerValidationSupportTest {
|
||||||
|
|
||||||
|
private InMemoryTerminologyServerValidationSupport mySvc;
|
||||||
|
private FhirContext myCtx = FhirContext.forR4();
|
||||||
|
private DefaultProfileValidationSupport myDefaultSupport;
|
||||||
|
private ValidationSupportChain myChain;
|
||||||
|
private PrePopulatedValidationSupport myPrePopulated;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before( ){
|
||||||
|
mySvc = new InMemoryTerminologyServerValidationSupport(myCtx);
|
||||||
|
myDefaultSupport = new DefaultProfileValidationSupport(myCtx);
|
||||||
|
myPrePopulated = new PrePopulatedValidationSupport(myCtx);
|
||||||
|
myChain = new ValidationSupportChain(mySvc,myPrePopulated, myDefaultSupport);
|
||||||
|
|
||||||
|
// Force load
|
||||||
|
myDefaultSupport.fetchCodeSystem("http://foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInUnknownCodeSystemWithEnumeratedValueSet() {
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
vs.setUrl("http://vs");
|
||||||
|
vs
|
||||||
|
.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem("http://cs")
|
||||||
|
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code1")))
|
||||||
|
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code2")));
|
||||||
|
myPrePopulated.addValueSet(vs);
|
||||||
|
|
||||||
|
ValidationSupportContext valCtx = new ValidationSupportContext(myChain);
|
||||||
|
ConceptValidationOptions options = new ConceptValidationOptions();
|
||||||
|
|
||||||
|
IValidationSupport.CodeValidationResult outcome = myChain.validateCodeInValueSet(valCtx, options, "http://cs", "code1", null, vs);
|
||||||
|
assertTrue(outcome.isOk());
|
||||||
|
|
||||||
|
outcome = myChain.validateCodeInValueSet(valCtx, options, "http://cs", "code99", null, vs);
|
||||||
|
assertNull(outcome);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue