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 {
|
||||
|
||||
private boolean myValidateDisplay;
|
||||
private boolean myInferSystem;
|
||||
|
||||
public boolean isInferSystem() {
|
||||
return myInferSystem;
|
||||
}
|
||||
|
@ -34,12 +37,19 @@ public class ConceptValidationOptions {
|
|||
return this;
|
||||
}
|
||||
|
||||
private boolean myInferSystem;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("inferSystem", myInferSystem)
|
||||
.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%
|
||||
*/
|
||||
|
||||
import org.thymeleaf.util.Validate;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -29,6 +31,7 @@ public class ValidationSupportContext {
|
|||
private final Set<String> myCurrentlyGeneratingSnapshots = new HashSet<>();
|
||||
|
||||
public ValidationSupportContext(IValidationSupport theRootValidationSupport) {
|
||||
Validate.notNull(theRootValidationSupport, "theRootValidationSupport musty not be null");
|
||||
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%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -41,31 +42,6 @@ public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> exten
|
|||
|
||||
void purgeCaches();
|
||||
|
||||
ValidateCodeResult 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;
|
||||
}
|
||||
}
|
||||
IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept, RequestDetails theRequestDetails);
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
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.isNotBlank;
|
||||
|
||||
|
@ -291,102 +293,14 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
|
|||
// nothing
|
||||
}
|
||||
|
||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||
public static String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||
}
|
||||
|
||||
@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) {
|
||||
List<IIdType> valueSetIds;
|
||||
|
||||
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;
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
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;
|
||||
|
@ -29,14 +30,12 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
|||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
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.util.LogicUtil;
|
||||
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.InvalidRequestException;
|
||||
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.CodeableConcept;
|
||||
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.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
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 org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -81,7 +79,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
|||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class,"myJpaValidationSupportChain" );
|
||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class, "myJpaValidationSupportChain");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -264,108 +262,10 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
|||
}
|
||||
|
||||
@Override
|
||||
public IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
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;
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -395,4 +295,8 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
|||
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.rest.api.server.storage.TransactionDetails;
|
||||
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.server.exceptions.InternalErrorException;
|
||||
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.FilterOperator;
|
||||
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
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.isNotBlank;
|
||||
|
||||
|
@ -243,108 +242,11 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
}
|
||||
|
||||
@Override
|
||||
public ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
List<IIdType> valueSetIds = Collections.emptyList();
|
||||
|
||||
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;
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.r5;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
|
@ -55,6 +56,8 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
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 org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -245,108 +248,10 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
}
|
||||
|
||||
@Override
|
||||
public ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
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;
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
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.server.exceptions.InvalidRequestException;
|
||||
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;
|
||||
|
||||
|
@ -142,21 +145,27 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
Parameters retVal = new Parameters();
|
||||
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;
|
||||
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
return (Parameters) toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
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) {
|
||||
boolean haveOne = false;
|
||||
for (boolean next : theBooleans) {
|
||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
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.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -148,16 +150,8 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(url, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
Parameters retVal = new Parameters();
|
||||
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;
|
||||
IValidationSupport.CodeValidationResult result = dao.validateCode(url, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
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.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -134,16 +136,8 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
Parameters retVal = new Parameters();
|
||||
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;
|
||||
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.provider.r5;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
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.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -134,16 +136,8 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
Parameters retVal = new Parameters();
|
||||
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;
|
||||
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
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.IDao;
|
||||
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.TranslationRequest;
|
||||
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.ITermReadSvc;
|
||||
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.rest.api.Constants;
|
||||
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.ResourceNotFoundException;
|
||||
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.UrlUtil;
|
||||
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.query.dsl.BooleanJunction;
|
||||
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.instance.model.api.IAnyResource;
|
||||
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.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CanonicalType;
|
||||
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.isNoneBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
|
||||
|
||||
public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||
public static final int DEFAULT_FETCH_SIZE = 250;
|
||||
|
@ -653,7 +659,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
includedConcepts = theIncludeOrExclude
|
||||
.getConcept()
|
||||
.stream()
|
||||
.map(t->new VersionIndependentConcept(theIncludeOrExclude.getSystem(), t.getCode()))
|
||||
.map(t -> new VersionIndependentConcept(theIncludeOrExclude.getSystem(), t.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -665,7 +671,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
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()) {
|
||||
addOrRemoveCode(theValueSetCodeAccumulator, theAddedCodes, theAdd, nextSystem, next.getCode(), lookup.getCodeDisplay());
|
||||
foundCount++;
|
||||
|
@ -1249,8 +1255,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInPreExpandedValueSet(
|
||||
ValidationOptions theValidationOptions,
|
||||
protected IValidationSupport.CodeValidationResult validateCodeIsInPreExpandedValueSet(
|
||||
ConceptValidationOptions theValidationOptions,
|
||||
ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||
|
||||
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet.hasId(), "ValueSet.id is required");
|
||||
|
@ -1258,7 +1264,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
List<TermValueSetConcept> concepts = new ArrayList<>();
|
||||
if (isNotBlank(theCode)) {
|
||||
if (theValidationOptions.isGuessSystem()) {
|
||||
if (theValidationOptions.isInferSystem()) {
|
||||
concepts.addAll(myValueSetConceptDao.findByValueSetResourcePidAndCode(valueSetResourcePid.getIdAsLong(), theCode));
|
||||
} else if (isNotBlank(theSystem)) {
|
||||
concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theSystem, theCode));
|
||||
|
@ -1276,19 +1282,40 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (TermValueSetConcept concept : concepts) {
|
||||
if (isNotBlank(theDisplay) && theDisplay.equals(concept.getDisplay())) {
|
||||
return new IFhirResourceDaoValueSet.ValidateCodeResult(true, "Validation succeeded", concept.getDisplay());
|
||||
if (theValidationOptions.isValidateDisplay() && concepts.size() > 0) {
|
||||
for (TermValueSetConcept concept : concepts) {
|
||||
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()) {
|
||||
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) {
|
||||
|
@ -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() {
|
||||
return myDeferredStorageSvc != null && !myDeferredStorageSvc.isStorageQueueEmpty();
|
||||
}
|
||||
|
@ -2020,7 +2099,36 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
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);
|
||||
|
||||
// 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);
|
||||
if (pid != null) {
|
||||
if (isValueSetPreExpandedForCodeValidation(valueSet)) {
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult outcome = validateCodeIsInPreExpandedValueSet(new ValidationOptions(), valueSet, theCodeSystem, theCode, null, null, null);
|
||||
if (outcome != null && outcome.isResult()) {
|
||||
return Optional.of(new VersionIndependentConcept(theCodeSystem, theCode));
|
||||
}
|
||||
return validateCodeIsInPreExpandedValueSet(theValidationOptions, valueSet, theCodeSystem, theCode, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueSet canonicalValueSet = toCanonicalValueSet(valueSet);
|
||||
VersionIndependentConcept wantConcept = new VersionIndependentConcept(theCodeSystem, theCode);
|
||||
ValueSetExpansionOptions expansionOptions = new ValueSetExpansionOptions()
|
||||
.setFailOnMissingCodeSystem(false);
|
||||
CodeValidationResult retVal = null;
|
||||
if (valueSet != null) {
|
||||
retVal = new InMemoryTerminologyServerValidationSupport(myContext).validateCodeInValueSet(theValidationSupportContext, theValidationOptions, theCodeSystem, theCode, theDisplay, valueSet);
|
||||
} 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
|
||||
|
@ -2171,6 +2281,12 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract Coding toCanonicalCoding(@Nullable IBaseDatatype theCoding);
|
||||
|
||||
@Nullable
|
||||
protected abstract CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept);
|
||||
|
||||
public static class Job implements HapiJob {
|
||||
@Autowired
|
||||
private ITermReadSvc myTerminologySvc;
|
||||
|
|
|
@ -20,18 +20,23 @@ package ca.uhn.fhir.jpa.term;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
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.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
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.utilities.validation.ValidationOptions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -132,8 +137,34 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@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();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
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.dstu3.model.CodeSystem;
|
||||
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.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public void expandValueSet(ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator) {
|
||||
ValueSet valueSetToExpand = (ValueSet) theValueSetToExpand;
|
||||
|
@ -130,35 +147,6 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
|||
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
|
||||
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
||||
return super.lookupCode(theSystem, theCode);
|
||||
|
@ -170,7 +158,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
|||
}
|
||||
|
||||
@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");
|
||||
ValueSet valueSet = (ValueSet) theValueSet;
|
||||
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.ValidationSupportContext;
|
||||
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.term.api.ITermReadSvcR4;
|
||||
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.IBaseResource;
|
||||
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.utilities.validation.ValidationOptions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -98,50 +89,29 @@ public class TermReadSvcR4 extends BaseTermReadSvcImpl implements ITermReadSvcR4
|
|||
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
|
||||
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
|
||||
return super.lookupCode(theSystem, theCode);
|
||||
}
|
||||
|
||||
@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;
|
||||
Coding coding = (Coding) theCoding;
|
||||
CodeableConcept codeableConcept = (CodeableConcept) theCodeableConcept;
|
||||
Coding coding = toCanonicalCoding(theCoding);
|
||||
CodeableConcept codeableConcept = toCanonicalCodeableConcept(theCodeableConcept);
|
||||
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
|
||||
public boolean isValueSetPreExpandedForCodeValidation(IBaseResource 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.ValueSetExpansionOptions;
|
||||
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.term.api.ITermReadSvcR5;
|
||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||
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.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
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.Coding;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
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 java.util.Optional;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -86,57 +80,18 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
|
|||
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
|
||||
public FhirContext getFhirContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
@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");
|
||||
ValueSet valueSet = (ValueSet) theValueSet;
|
||||
org.hl7.fhir.r4.model.ValueSet valueSetR4 = toCanonicalValueSet(valueSet);
|
||||
|
||||
Coding coding = (Coding) 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());
|
||||
}
|
||||
org.hl7.fhir.r4.model.Coding codingR4 = toCanonicalCoding(theCoding);
|
||||
|
||||
CodeableConcept codeableConcept = (CodeableConcept) theCodeableConcept;
|
||||
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
|
||||
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);
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
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.ValueSetExpansionOptions;
|
||||
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.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
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 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.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.ConceptMap;
|
||||
|
@ -105,7 +108,12 @@ public interface ITermReadSvc extends IValidationSupport {
|
|||
/**
|
||||
* 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);
|
||||
|
||||
|
@ -114,5 +122,4 @@ public interface ITermReadSvc extends IValidationSupport {
|
|||
*/
|
||||
boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
|
||||
retVal.setDriver(new org.h2.Driver());
|
||||
retVal.setUrl("jdbc:h2:mem:testdb_r4");
|
||||
retVal.setMaxWaitMillis(10000);
|
||||
retVal.setMaxWaitMillis(30000);
|
||||
retVal.setUsername("");
|
||||
retVal.setPassword("");
|
||||
retVal.setMaxTotal(ourMaxThreads);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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.CodingDt;
|
||||
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.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
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.Test;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -40,30 +38,42 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
public void testValidateCodeOperationByCodeAndSystemBadCode() {
|
||||
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://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemGood() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
public void testValidateCodeOperationByCodeAndSystemBadSystem() {
|
||||
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;
|
||||
CodeDt code = new CodeDt("8450-9");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt 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());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,8 +85,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
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");
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isOk());
|
||||
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
|
||||
|
@ -103,8 +114,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -117,8 +128,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -131,8 +142,8 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
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.TermValueSetPreExpansionStatusEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
@ -62,7 +61,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
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");
|
||||
CodeType code = new CodeType();
|
||||
CodeType system = new CodeType("urn:iso:std:iso:3166");
|
||||
|
@ -70,12 +69,12 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
// Validate good
|
||||
code.setValue("NL");
|
||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||
assertEquals(true, validationOutcome.isResult());
|
||||
assertEquals(true, validationOutcome.isOk());
|
||||
|
||||
// Validate bad
|
||||
code.setValue("QQ");
|
||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||
assertEquals(false, validationOutcome.isResult());
|
||||
assertEquals(false, validationOutcome.isOk());
|
||||
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
|
||||
|
@ -87,12 +86,12 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
// Validate good
|
||||
code.setValue("NL");
|
||||
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
|
||||
assertEquals(true, validationOutcome.isResult());
|
||||
assertEquals(true, validationOutcome.isOk());
|
||||
|
||||
// Validate bad
|
||||
code.setValue("QQ");
|
||||
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\"/>")));
|
||||
}
|
||||
|
||||
@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
|
||||
public void testValidateCodeOperationByIdentifierAndCodeAndSystem() {
|
||||
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;
|
||||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
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");
|
||||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isOk());
|
||||
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");
|
||||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -267,8 +239,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
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());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -282,8 +254,8 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
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 code = new StringType("male");
|
||||
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());
|
||||
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));
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setId("ABC");
|
||||
p.setActive(true);
|
||||
|
@ -130,7 +130,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
p.addIdentifier().setValue("VAL" + i);
|
||||
|
@ -185,7 +185,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
});
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
// Submit an update
|
||||
Patient p = new Patient();
|
||||
p.setId(patientId);
|
||||
|
@ -224,7 +224,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setId("ABC");
|
||||
p.setActive(true);
|
||||
|
@ -260,7 +260,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testNoRetryInterceptor() {
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setId("ABC");
|
||||
p.setActive(true);
|
||||
|
@ -300,7 +300,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.emptyList());
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setId("ABC");
|
||||
p.setActive(true);
|
||||
|
@ -345,7 +345,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
IIdType pId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
|
||||
Parameters patch = new Parameters();
|
||||
Parameters.ParametersParameterComponent operation = patch.addParameter();
|
||||
|
@ -382,7 +382,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
// Make sure we saved the object
|
||||
Patient patient = myPatientDao.read(pId);
|
||||
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());
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
|
||||
Patient p = new Patient();
|
||||
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.model.entity.ResourceTable;
|
||||
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.ITermLoaderSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
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.CanonicalType;
|
||||
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.Condition;
|
||||
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.Group;
|
||||
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.Patient;
|
||||
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.QuestionnaireResponse;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
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.r5.utils.IResourceValidator;
|
||||
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.junit.jupiter.api.Assertions.assertEquals;
|
||||
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.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -95,6 +103,105 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
@Autowired
|
||||
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
|
||||
*/
|
||||
|
@ -591,16 +698,10 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
obs.getCode().getCodingFirstRep().setSystem("http://example.com/codesystem");
|
||||
obs.getCode().getCodingFirstRep().setCode("foo-foo");
|
||||
obs.getCode().getCodingFirstRep().setDisplay("Some Code");
|
||||
try {
|
||||
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));
|
||||
fail();
|
||||
} 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());
|
||||
}
|
||||
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));
|
||||
assertEquals("Unknown code in fragment CodeSystem 'http://example.com/codesystem#foo-foo'", outcome.getIssueFirstRep().getDiagnostics());
|
||||
assertEquals(OperationOutcome.IssueSeverity.WARNING, outcome.getIssueFirstRep().getSeverity());
|
||||
|
||||
// Correct codesystem, Code in 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;
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
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.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.IPrimitiveType;
|
||||
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.UriType;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -49,14 +48,14 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
public void before02() throws IOException {
|
||||
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
|
||||
CodeSystem upload2 = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
|
||||
myCodeSystemDao.create(upload2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
||||
public void testValidateCodeOperationNoValueSet() {
|
||||
UriType valueSetIdentifier = null;
|
||||
IdType id = null;
|
||||
CodeType code = new CodeType("8450-9-XXX");
|
||||
|
@ -64,22 +63,12 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
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());
|
||||
try {
|
||||
myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -91,8 +80,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
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());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
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");
|
||||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertFalse(result.isOk());
|
||||
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
|
||||
|
@ -119,8 +109,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
StringType display = new StringType("Systolic blood pressure at First encounter");
|
||||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = null;
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -134,8 +124,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -151,18 +141,18 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||
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());
|
||||
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -175,8 +165,8 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
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());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -191,18 +181,18 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
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());
|
||||
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
myTerminologyDeferredStorageSvc.saveDeferred();
|
||||
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());
|
||||
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -213,17 +203,17 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
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("<contains>"));
|
||||
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
|
||||
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("<system value=\"http://acme.org\"/>"));
|
||||
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("</expansion>"));
|
||||
|
||||
|
@ -236,12 +226,12 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
assertThat(resp, stringContainsInOrder(
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSet_ExceedsMaxSize() {
|
||||
// Add a bunch of codes
|
||||
|
@ -265,7 +255,7 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
|
||||
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 code = new StringType("male");
|
||||
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());
|
||||
assertTrue( result.isResult(), result.getMessage());
|
||||
assertTrue(result.isOk(), result.getMessage());
|
||||
assertEquals("Male", result.getDisplay());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -45,23 +45,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
||||
.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"))
|
||||
.withParameter(Parameters.class, "code", new CodeDt("11378-7"))
|
||||
.andParameter("system", new UriDt("http://loinc.org"))
|
||||
.execute();
|
||||
|
||||
|
|
|
@ -749,6 +749,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||
.andParameter("system", new UriType("http://acme.org"))
|
||||
.andParameter("url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
|
||||
.execute();
|
||||
|
||||
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(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
||||
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -810,11 +808,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
||||
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
}
|
||||
|
||||
@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.TermValueSetConceptDesignation;
|
||||
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.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.ResourceNotFoundException;
|
||||
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_VALUE_SET;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||
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.assertNotNull;
|
||||
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.fail;
|
||||
|
||||
|
@ -98,11 +98,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
|
||||
private void persistCodeSystem(CodeSystem theCodeSystem) {
|
||||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
|
||||
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
|
||||
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
});
|
||||
myCodeSystemDao.readEntity(myExtensionalCsId, null).getId();
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
createLocalVsWithUnknownCode(codeSystem);
|
||||
}
|
||||
|
||||
private void createLocalCsAndVs() {
|
||||
private void createLocalCs() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||
|
@ -671,8 +671,8 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
.named("$expand")
|
||||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(ValueSet.class)
|
||||
.execute();
|
||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||
.execute();
|
||||
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||
|
||||
// Update the CodeSystem URL and Codes
|
||||
|
@ -696,12 +696,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(ValueSet.class)
|
||||
.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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* #516
|
||||
*/
|
||||
|
@ -796,7 +795,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
}
|
||||
|
||||
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
||||
runInTransaction(()->{
|
||||
runInTransaction(() -> {
|
||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||
|
||||
|
@ -814,7 +813,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
}
|
||||
|
||||
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
||||
runInTransaction(()->{
|
||||
runInTransaction(() -> {
|
||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||
|
||||
|
@ -906,10 +905,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
||||
createLocalCsAndVs();
|
||||
createLocalCs();
|
||||
createLocalVsWithIncludeConcept();
|
||||
|
||||
String url = ourServerBase +
|
||||
"/ValueSet/$validate-code?system=" +
|
||||
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||
"&code=AA";
|
||||
|
||||
|
@ -926,7 +926,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException {
|
||||
createLocalCsAndVs();
|
||||
createLocalCs();
|
||||
createLocalVsWithIncludeConcept();
|
||||
|
||||
String url = ourServerBase +
|
||||
|
@ -953,7 +953,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||
.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());
|
||||
}
|
||||
|
||||
@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
|
||||
public void testValidateCodeAgainstBuiltInSystem() {
|
||||
Parameters respParam = myClient
|
||||
|
@ -983,11 +1001,8 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("succeeded"));
|
||||
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1018,7 +1033,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
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)) {
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response: {}", response);
|
||||
|
@ -1026,7 +1041,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
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);
|
||||
|
@ -1070,7 +1085,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import ca.uhn.fhir.jpa.entity.TermValueSet;
|
|||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||
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.term.api.ITermCodeSystemStorageSvc;
|
||||
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.ResourceNotFoundException;
|
||||
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_VALUE_SET;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||
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.assertNotNull;
|
||||
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.fail;
|
||||
|
||||
|
@ -983,8 +983,8 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
.named("$expand")
|
||||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(ValueSet.class)
|
||||
.execute();
|
||||
ourLog.info("Expanded: {}",myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||
.execute();
|
||||
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||
|
||||
// Update the CodeSystem URL and Codes
|
||||
|
@ -1008,12 +1008,11 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(ValueSet.class)
|
||||
.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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* #516
|
||||
*/
|
||||
|
@ -1108,7 +1107,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
}
|
||||
|
||||
private void validateTermValueSetNotExpanded(String theValueSetName) {
|
||||
runInTransaction(()->{
|
||||
runInTransaction(() -> {
|
||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||
|
||||
|
@ -1126,7 +1125,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
}
|
||||
|
||||
private void validateTermValueSetExpandedAndChildren(String theValueSetName, CodeSystem theCodeSystem) {
|
||||
runInTransaction(()->{
|
||||
runInTransaction(() -> {
|
||||
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable);
|
||||
assertTrue(optionalValueSetByResourcePid.isPresent());
|
||||
|
||||
|
@ -1219,9 +1218,10 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
||||
createLocalCsAndVs();
|
||||
createLocalVsWithIncludeConcept();
|
||||
|
||||
String url = ourServerBase +
|
||||
"/ValueSet/$validate-code?system=" +
|
||||
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||
"&code=AA";
|
||||
|
||||
|
@ -1265,7 +1265,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||
.andParameter("system", new UriType("http://acme.org"))
|
||||
|
@ -1297,12 +1297,10 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("succeeded"));
|
||||
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Male", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
}
|
||||
|
||||
// Good code and system, but not in specified valueset
|
||||
{
|
||||
Parameters respParam = myClient
|
||||
|
@ -1322,7 +1320,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
assertEquals(false, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
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)) {
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||
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)) {
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response: {}", response);
|
||||
|
@ -1362,7 +1361,32 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
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)) {
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Response: {}", response);
|
||||
|
@ -1407,7 +1431,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,8 @@ package ca.uhn.fhir.jpa.term;
|
|||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
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.term.api.ITermLoaderSvc;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
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.StringType;
|
||||
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.instance.model.api.IPrimitiveType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -30,12 +28,12 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||
|
@ -228,11 +226,13 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
|||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||
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());
|
||||
assertEquals("Found code", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("R' wave amplitude in lead I", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -240,11 +240,13 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
|||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||
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());
|
||||
assertEquals("Code not found", result.getMessage());
|
||||
assertFalse(result.isOk());
|
||||
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) {
|
||||
|
|
|
@ -3,7 +3,6 @@ package ca.uhn.fhir.jpa.term;
|
|||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
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.entity.TermConceptMap;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
|
||||
|
@ -43,8 +42,8 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
|
||||
public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(TerminologySvcImplR4Test.class);
|
||||
ValidationOptions optsNoGuess = new ValidationOptions();
|
||||
ValidationOptions optsGuess = new ValidationOptions().guessSystem();
|
||||
ConceptValidationOptions optsNoGuess = new ConceptValidationOptions();
|
||||
ConceptValidationOptions optsGuess = new ConceptValidationOptions().setInferSystem(true);
|
||||
private IIdType myConceptMapId;
|
||||
|
||||
private void createAndPersistConceptMap() {
|
||||
|
@ -1799,42 +1798,37 @@ public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
|||
|
||||
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);
|
||||
|
||||
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);
|
||||
assertNull(result);
|
||||
assertFalse(result.isOk());
|
||||
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
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);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
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);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
||||
codeableConcept.addCoding(coding);
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
|
@ -1852,43 +1846,38 @@ public class TerminologySvcImplR4Test extends BaseTermR4Test {
|
|||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
assertNull(result);
|
||||
assertFalse(result.isOk());
|
||||
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsGuess, valueSet, null, "11378-7", null, null, null);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
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);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, "http://acme.org", "11378-7", null, null, null);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
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);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
codeableConcept.addCoding(new Coding("BOGUS", "BOGUS", "BOGUS"));
|
||||
codeableConcept.addCoding(coding);
|
||||
result = myTermSvc.validateCodeIsInPreExpandedValueSet(optsNoGuess, valueSet, null, null, null, null, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Validation succeeded", result.getMessage());
|
||||
assertTrue(result.isOk());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
<code value="8450-9" />
|
||||
<display value="Systolic blood pressure--expiration" />
|
||||
</concept>
|
||||
<concept>
|
||||
<code value="11378-7" />
|
||||
<display value="Systolic blood pressure at First encounter" />
|
||||
</concept>
|
||||
</codeSystem>
|
||||
<compose>
|
||||
<include>
|
||||
|
@ -124,4 +128,4 @@
|
|||
</concept>
|
||||
</include>
|
||||
</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.ValidationSupportContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.util.VersionIndependentConcept;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.convertors.conv10_50.ValueSet10_50;
|
||||
|
@ -26,6 +27,8 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
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) {
|
||||
org.hl7.fhir.r5.model.ValueSet expansionR5;
|
||||
switch (myCtx.getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
switch (theValueSetToExpand.getStructureFhirVersionEnum()) {
|
||||
case DSTU2: {
|
||||
expansionR5 = expandValueSetDstu2(theValidationSupportContext, (ca.uhn.fhir.model.dstu2.resource.ValueSet) theValueSetToExpand, theWantSystem, theWantCode);
|
||||
break;
|
||||
}
|
||||
case DSTU2_HL7ORG: {
|
||||
expansionR5 = expandValueSetDstu2Hl7Org(theValidationSupportContext, (ValueSet) theValueSetToExpand, theWantSystem, theWantCode);
|
||||
break;
|
||||
|
@ -122,11 +128,11 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
@Override
|
||||
public CodeValidationResult
|
||||
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) {
|
||||
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();
|
||||
|
||||
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;
|
||||
|
||||
boolean caseSensitive = true;
|
||||
|
@ -269,11 +275,20 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
}
|
||||
if (codeMatches) {
|
||||
if (theOptions.isInferSystem() || nextExpansionCode.getSystem().equals(theCodeSystem)) {
|
||||
return new CodeValidationResult()
|
||||
.setCode(theCode)
|
||||
.setDisplay(nextExpansionCode.getDisplay())
|
||||
.setCodeSystemName(codeSystemName)
|
||||
.setCodeSystemVersion(codeSystemVersion);
|
||||
if (!theOptions.isValidateDisplay() || (isBlank(nextExpansionCode.getDisplay()) || isBlank(theDisplay) || nextExpansionCode.getDisplay().equals(theDisplay))) {
|
||||
return new CodeValidationResult()
|
||||
.setCode(theCode)
|
||||
.setDisplay(nextExpansionCode.getDisplay())
|
||||
.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);
|
||||
}
|
||||
|
||||
@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
|
||||
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
|
||||
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 -> {
|
||||
|
@ -452,6 +502,33 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
addCodes(system, codesList, nextCodeList, wantCodes);
|
||||
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.support.IValidationSupport;
|
||||
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.PreconditionFailedException;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -18,6 +19,8 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
/**
|
||||
* Simple validation support module that handles profile snapshot generation.
|
||||
* <p>
|
||||
|
@ -75,9 +78,14 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
|||
}
|
||||
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) {
|
||||
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);
|
||||
|
@ -112,6 +120,8 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
|||
|
||||
return theInput;
|
||||
|
||||
} catch (BaseServerResponseException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new InternalErrorException("Failed to generate snapshot", e);
|
||||
} 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