Merge remote-tracking branch 'origin/master' into gg_20201105-remove-person-references
This commit is contained in:
commit
2a3b72db17
|
@ -93,4 +93,10 @@ public class ValueSetExpansionOptions {
|
|||
myFailOnMissingCodeSystem = theFailOnMissingCodeSystem;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static ValueSetExpansionOptions forOffsetAndCount(int theOffset, int theCount) {
|
||||
return new ValueSetExpansionOptions()
|
||||
.setOffset(theOffset)
|
||||
.setCount(theCount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlMultipleMatches=Invalid match
|
|||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.uniqueIndexConflictFailure=Can not create resource of type {0} as it would create a duplicate index matching query: {1} (existing index belongs to {2})
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.uniqueIndexConflictFailure=Can not create resource of type {0} as it would create a duplicate unique index matching query: {1} (existing index belongs to {2}, new unique index created by {3})
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionContainsMultipleWithDuplicateId=Transaction bundle contains multiple resources with ID: {0}
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionEntryHasInvalidVerb=Transaction bundle entry has missing or invalid HTTP Verb specified in Bundle.entry({1}).request.method. Found value: "{0}"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2175
|
||||
title: "Expanding a ValueSet using a filter now evaluates the display with left-matching
|
||||
by string token, case-insensitive."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2182
|
||||
title: "When a unique index SearchParametr violation is blocked, the error message will now include the ID of the relevant
|
||||
SearchParameter, in order to make troubleshooting easier."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2183
|
||||
title: "The `CodeSystem/$subsumes` operation inadvertantly reversed the meanings of the CodeA and CodeB parameters, resulting
|
||||
in `subsumes` and `subsumed-by` responses being reversed. This has been corrected. Thanks to Rob Hausam for reporting!"
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2195
|
||||
title: "When performing a ValueSet expansion with a filter a large pre-expanded
|
||||
ValueSet (more than 1000 codes), the filter failed to find concepts appearing
|
||||
after the first thousand. This has been corrected."
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: change
|
||||
issue: 2197
|
||||
title: The resource IDs for several LOINC resources were corrected. Thanks to Steven Wagers for the pull request!
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- item:
|
||||
type: "add"
|
||||
title: "The version of a few dependencies have been bumped to the latest versions
|
||||
(dependent HAPI modules listed in brackets):
|
||||
<ul>
|
||||
<li>Jetty (JPA Starter): 9.4.30.v20200611 -> 9.4.34.v20201102</li>
|
||||
</ul>"
|
|
@ -87,6 +87,20 @@ The following snippet shows a server with this configuration.
|
|||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/PartitionExamples.java|multitenantServer}}
|
||||
```
|
||||
|
||||
Once enabled, HTTP Requests to the FHIR server must include the name of the partition in the request, for identification purposes. With no multitenancy, a request to create a Patient could look like this:
|
||||
|
||||
```HTTP
|
||||
POST www.example.com/fhir/Patient
|
||||
```
|
||||
|
||||
With partitioning enabled, if we were to now create a patient in the `DEFAULT` paritition, the request would now look like this:
|
||||
|
||||
|
||||
```
|
||||
POST www.example.com/fhir/DEFAULT/Patient
|
||||
```
|
||||
|
||||
Failure to add a partition name to the request path will result in an error when multitenancy is enabled.
|
||||
|
||||
# Limitations
|
||||
|
||||
|
|
|
@ -46,11 +46,13 @@ The `$partition-management-create-partition` operation can be used to create a n
|
|||
</table>
|
||||
|
||||
### Example
|
||||
Note that once multitenancy is enabled, all requests to the FHIR server must contain a tenant. These operations are no exception.
|
||||
If you fail to include a tenant identifier in the request, an error will be returned.
|
||||
|
||||
An HTTP POST to the following URL would be used to invoke this operation:
|
||||
An HTTP POST to the following URL would be used to invoke this operation. Notice that we use the DEFAULT partition, as it always exists by default.
|
||||
|
||||
```url
|
||||
http://example.com/$partition-management-create-partition
|
||||
http://example.com/DEFAULT/$partition-management-create-partition
|
||||
```
|
||||
|
||||
The following request body could be used:
|
||||
|
@ -117,7 +119,7 @@ The `$partition-management-update-partition` operation can be used to update an
|
|||
An HTTP POST to the following URL would be used to invoke this operation:
|
||||
|
||||
```url
|
||||
http://example.com/$partition-management-update-partition
|
||||
http://example.com/DEFAULT/$partition-management-update-partition
|
||||
```
|
||||
|
||||
The following request body could be used:
|
||||
|
@ -168,7 +170,7 @@ The `$partition-management-delete-partition` operation can be used to delete an
|
|||
An HTTP POST to the following URL would be used to invoke this operation:
|
||||
|
||||
```url
|
||||
http://example.com/$partition-management-delete-partition
|
||||
http://example.com/DEFAULT/$partition-management-delete-partition
|
||||
```
|
||||
|
||||
The following request body could be used:
|
||||
|
|
|
@ -49,7 +49,7 @@ The CLI tool can be used to start a local, fully functional FHIR server which yo
|
|||
|
||||
<img src="/hapi-fhir/docs/images/hapi-fhir-cli-run-server.png" alt="Run Server" style="margin-left: 40px;"/>
|
||||
|
||||
Once the server has started, you can access the testing webpage by pointing your browser at <a href="http://localhost:8080/">http://localhost:8080/</a>. The FHIR server base URL will be <a href="http://localhost:8080/baseDstu2/">http://localhost:8080/baseDstu2/</a>.
|
||||
Once the server has started, you can access the testing webpage by pointing your browser at <a href="http://localhost:8080/">http://localhost:8080/</a>. The FHIR server base URL will be <a href="http://localhost:8080/baseDstu3/">http://localhost:8080/baseDstu3/</a>.
|
||||
|
||||
Note that by default this server will not be populated with any resources at all. You can easily populate it with the FHIR example resources by <b>leaving it running</b> and opening a second terminal window, then using the <code>hapi-fhir-cli upload-examples</code> command (see the section below).
|
||||
|
||||
|
@ -59,7 +59,7 @@ The server uses a local Derby database instance for storage. You may want to exe
|
|||
|
||||
The <b>upload-examples</b> command downloads the complete set of FHIR example resources from the HL7 website, and uploads them to a server of your choice. This can be useful to populate a server with test data.
|
||||
|
||||
To execute this command, uploading test resources to a local CLI server, issue the following: `hapi-fhir-cli upload-examples -t http://localhost:8080/baseDstu2`
|
||||
To execute this command, uploading test resources to a local CLI server, issue the following: `hapi-fhir-cli upload-examples -v dstu3 -t http://localhost:8080/baseDstu3`
|
||||
|
||||
Note that this command may take a surprisingly long time to complete because of the large number of examples.
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package ca.uhn.hapi.fhir.docs;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.collections4.IteratorUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class ChangelogFilesTest {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(ChangelogFilesTest.class);
|
||||
|
||||
@Test
|
||||
public void testChangelogFiles() {
|
||||
Collection<File> files = FileUtils.listFiles(
|
||||
new File("src/main/resources/ca/uhn/hapi/fhir/changelog"),
|
||||
new String[]{"yaml"},
|
||||
true);
|
||||
|
||||
for (File next : files) {
|
||||
ourLog.info("Checking file: {}", next);
|
||||
|
||||
String nextFilename = next.getName();
|
||||
if (nextFilename.equals("changes.yaml")) {
|
||||
continue;
|
||||
}
|
||||
if (nextFilename.equals("version.yaml")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!nextFilename.matches("[a-zA-Z0-9]+-[a-zA-Z0-9_-]+\\.yaml")) {
|
||||
fail("Invalid changelog filename: " + next);
|
||||
}
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||
ObjectNode tree;
|
||||
try (FileInputStream fis = new FileInputStream(next)) {
|
||||
tree = (ObjectNode) mapper.readTree(new InputStreamReader(fis, Charsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException("Failed to read " + next, e);
|
||||
}
|
||||
|
||||
List<String> fieldNames = IteratorUtils.toList(tree.fieldNames());
|
||||
boolean title = fieldNames.remove("title");
|
||||
assertTrue(title, "No 'title' element in " + next);
|
||||
|
||||
boolean type = fieldNames.remove("type");
|
||||
assertTrue(type, "No 'type' element in " + next);
|
||||
|
||||
// this one is optional
|
||||
boolean haveIssue = fieldNames.remove("issue");
|
||||
|
||||
assertThat("Invalid element in " + next + ": " + fieldNames, fieldNames, empty());
|
||||
|
||||
if (haveIssue) {
|
||||
String issue = tree.get("issue").asText();
|
||||
try {
|
||||
Integer.parseInt(issue);
|
||||
} catch (NumberFormatException e) {
|
||||
fail("Invalid issue value in " + next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ public interface ITermValueSetConceptViewDao extends JpaRepository<TermValueSetC
|
|||
@Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptOrder >= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder")
|
||||
List<TermValueSetConceptView> findByTermValueSetId(@Param("from") int theFrom, @Param("to") int theTo, @Param("pid") Long theValueSetId);
|
||||
|
||||
@Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptDisplay LIKE :display ORDER BY v.myConceptOrder")
|
||||
@Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND LOWER(v.myConceptDisplay) LIKE :display ORDER BY v.myConceptOrder")
|
||||
List<TermValueSetConceptView> findByTermValueSetId(@Param("pid") Long theValueSetId, @Param("display") String theDisplay);
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
|
||||
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.dao.BaseHapiFhirResourceDao;
|
||||
|
@ -31,216 +30,60 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
|||
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.hl7.fhir.convertors.conv30_40.ValueSet30_40;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
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 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;
|
||||
import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
|
||||
|
||||
public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class, "myJpaValidationSupportChain");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) {
|
||||
org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theFilter, theOffset, theCount);
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource) {
|
||||
validateIncludes("include", theSource.getCompose().getInclude());
|
||||
validateIncludes("exclude", theSource.getCompose().getExclude());
|
||||
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), null, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource, int theOffset, int theCount) {
|
||||
validateIncludes("include", theSource.getCompose().getInclude());
|
||||
validateIncludes("exclude", theSource.getCompose().getExclude());
|
||||
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions()
|
||||
.setOffset(theOffset)
|
||||
.setCount(theCount);
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
}
|
||||
|
||||
private void validateIncludes(String name, List<ConceptSetComponent> listToValidate) {
|
||||
for (ConceptSetComponent nextExclude : listToValidate) {
|
||||
if (isBlank(nextExclude.getSystem()) && nextExclude.getValueSet().isEmpty() && !ElementUtil.isEmpty(nextExclude.getConcept(), nextExclude.getFilter())) {
|
||||
throw new InvalidRequestException("ValueSet contains " + name + " criteria with no system defined");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, theUri, theFilter);
|
||||
return ValueSet30_40.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
return doExpand(source);
|
||||
|
||||
// if (defaultValueSet != null) {
|
||||
// source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet));
|
||||
// } else {
|
||||
// IBundleProvider ids = search(ValueSet.SP_URL, new UriParam(theUri));
|
||||
// if (ids.size() == 0) {
|
||||
// throw new InvalidRequestException("Unknown ValueSet URI: " + theUri);
|
||||
// }
|
||||
// source = (ValueSet) ids.getResources(0, 1).get(0);
|
||||
// }
|
||||
//
|
||||
// return expand(defaultValueSet, theFilter);
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) {
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, theUri, theFilter);
|
||||
return ValueSet30_40.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
return doExpand(source, theOffset, theCount);
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, canonicalInput, theFilter);
|
||||
return ValueSet30_40.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
|
||||
// for (UriType next : theSource.getCompose().getInclude()) {
|
||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||
// include.setSystem(next.getValue());
|
||||
// addFilterIfPresent(theFilter, include);
|
||||
// }
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter, int theOffset, int theCount) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
toExpand.setId(theSource.getId());
|
||||
toExpand.setUrl(theSource.getUrl());
|
||||
if (theSource.getVersion() != null) {
|
||||
toExpand.setVersion(theSource.getVersion());
|
||||
}
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand, theOffset, theCount);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void applyFilter(IntegerType theTotalElement, List<ValueSetExpansionContainsComponent> theContains, String theFilter) {
|
||||
|
||||
for (int idx = 0; idx < theContains.size(); idx++) {
|
||||
ValueSetExpansionContainsComponent next = theContains.get(idx);
|
||||
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
|
||||
theContains.remove(idx);
|
||||
idx--;
|
||||
if (theTotalElement.getValue() != null) {
|
||||
theTotalElement.setValue(theTotalElement.getValue() - 1);
|
||||
}
|
||||
}
|
||||
applyFilter(theTotalElement, next.getContains(), theFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
||||
if (ElementUtil.isEmpty(include.getConcept())) {
|
||||
if (isNotBlank(theFilter)) {
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
|
||||
}
|
||||
}
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter, int theOffset, int theCount) {
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, canonicalInput, theFilter);
|
||||
return ValueSet30_40.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -206,7 +206,7 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
if (isNotBlank(nextQueryString)) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myCompositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString));
|
||||
theParams.myCompositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString, next.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,13 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
if (myDaoConfig.isUniqueIndexesCheckedBeforeSave()) {
|
||||
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
|
||||
if (existing != null) {
|
||||
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
|
||||
String searchParameterId = "(unknown)";
|
||||
if (next.getSearchParameterId() != null) {
|
||||
searchParameterId = next.getSearchParameterId().toUnqualifiedVersionless().getValue();
|
||||
}
|
||||
|
||||
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue(), searchParameterId);
|
||||
throw new PreconditionFailedException(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
|
|||
*/
|
||||
|
||||
if (modifier == TokenParamModifier.IN) {
|
||||
codes.addAll(myTerminologySvc.expandValueSet(null, code));
|
||||
codes.addAll(myTerminologySvc.expandValueSetIntoConceptList(null, code));
|
||||
} else if (modifier == TokenParamModifier.ABOVE) {
|
||||
system = determineSystemIfMissing(theSearchParam, code, system);
|
||||
validateHaveSystemAndCodeForToken(paramName, code, system);
|
||||
|
@ -273,7 +273,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
|
|||
String valueSet = valueSetUris.iterator().next();
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions()
|
||||
.setFailOnMissingCodeSystem(false);
|
||||
List<FhirVersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(options, valueSet);
|
||||
List<FhirVersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSetIntoConceptList(options, valueSet);
|
||||
for (FhirVersionIndependentConcept nextCandidate : candidateCodes) {
|
||||
if (nextCandidate.getCode().equals(code)) {
|
||||
retVal = nextCandidate.getSystem();
|
||||
|
|
|
@ -21,48 +21,28 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
*/
|
||||
|
||||
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.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
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.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.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
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 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;
|
||||
|
||||
public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class, "myJpaValidationSupportChain");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
|
@ -75,156 +55,26 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
return expand(source, theFilter, theOffset, theCount);
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource) {
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), null, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource, int theOffset, int theCount) {
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions()
|
||||
.setOffset(theOffset)
|
||||
.setCount(theCount);
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
return doExpand(source);
|
||||
|
||||
// if (defaultValueSet != null) {
|
||||
// source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet));
|
||||
// } else {
|
||||
// IBundleProvider ids = search(ValueSet.SP_URL, new UriParam(theUri));
|
||||
// if (ids.size() == 0) {
|
||||
// throw new InvalidRequestException("Unknown ValueSet URI: " + theUri);
|
||||
// }
|
||||
// source = (ValueSet) ids.getResources(0, 1).get(0);
|
||||
// }
|
||||
//
|
||||
// return expand(defaultValueSet, theFilter);
|
||||
return myTerminologySvc.expandValueSet(null, theUri, theFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
return doExpand(source, theOffset, theCount);
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
return myTerminologySvc.expandValueSet(options, theUri, theFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
|
||||
// for (UriType next : theSource.getCompose().getInclude()) {
|
||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||
// include.setSystem(next.getValue());
|
||||
// addFilterIfPresent(theFilter, include);
|
||||
// }
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return myTerminologySvc.expandValueSet(null, theSource, theFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter, int theOffset, int theCount) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
toExpand.setId(theSource.getId());
|
||||
toExpand.setUrl(theSource.getUrl());
|
||||
if (theSource.getVersion() != null) {
|
||||
toExpand.setVersion(theSource.getVersion());
|
||||
}
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand, theOffset, theCount);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void applyFilter(IntegerType theTotalElement, List<ValueSetExpansionContainsComponent> theContains, String theFilter) {
|
||||
|
||||
for (int idx = 0; idx < theContains.size(); idx++) {
|
||||
ValueSetExpansionContainsComponent next = theContains.get(idx);
|
||||
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
|
||||
theContains.remove(idx);
|
||||
idx--;
|
||||
if (theTotalElement.getValue() != null) {
|
||||
theTotalElement.setValue(theTotalElement.getValue() - 1);
|
||||
}
|
||||
}
|
||||
applyFilter(theTotalElement, next.getContains(), theFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
||||
if (ElementUtil.isEmpty(include.getConcept())) {
|
||||
if (isNotBlank(theFilter)) {
|
||||
include.addFilter().setProperty(JpaConstants.VALUESET_FILTER_DISPLAY).setOp(FilterOperator.EQUAL).setValue(theFilter);
|
||||
}
|
||||
}
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
return myTerminologySvc.expandValueSet(options, theSource, theFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,47 +21,28 @@ package ca.uhn.fhir.jpa.dao.r5;
|
|||
*/
|
||||
|
||||
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.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.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import org.hl7.fhir.convertors.conv40_50.ValueSet40_50;
|
||||
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.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
|
||||
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;
|
||||
|
||||
public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
myValidationSupport = getApplicationContext().getBean(IValidationSupport.class,"myJpaValidationSupportChain" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
|
@ -74,157 +55,32 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
return expand(source, theFilter, theOffset, theCount);
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource) {
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), null, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
|
||||
}
|
||||
|
||||
private ValueSet doExpand(ValueSet theSource, int theOffset, int theCount) {
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions()
|
||||
.setOffset(theOffset)
|
||||
.setCount(theCount);
|
||||
IValidationSupport.ValueSetExpansionOutcome retVal = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, theSource);
|
||||
validateHaveExpansionOrThrowInternalErrorException(retVal);
|
||||
return (ValueSet) retVal.getValueSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(Enumerations.FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
ValueSet retVal = doExpand(source);
|
||||
return retVal;
|
||||
|
||||
// if (defaultValueSet != null) {
|
||||
// source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet));
|
||||
// } else {
|
||||
// IBundleProvider ids = search(ValueSet.SP_URL, new UriParam(theUri));
|
||||
// if (ids.size() == 0) {
|
||||
// throw new InvalidRequestException("Unknown ValueSet URI: " + theUri);
|
||||
// }
|
||||
// source = (ValueSet) ids.getResources(0, 1).get(0);
|
||||
// }
|
||||
//
|
||||
// return expand(defaultValueSet, theFilter);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, theUri, theFilter);
|
||||
return ValueSet40_50.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException("URI must not be blank or missing");
|
||||
}
|
||||
|
||||
ValueSet source = new ValueSet();
|
||||
source.setUrl(theUri);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
ConceptSetFilterComponent filter = source.getCompose().addInclude().addValueSet(theUri).addFilter();
|
||||
filter.setProperty("display");
|
||||
filter.setOp(Enumerations.FilterOperator.EQUAL);
|
||||
filter.setValue(theFilter);
|
||||
} else {
|
||||
source.getCompose().addInclude().addValueSet(theUri);
|
||||
}
|
||||
|
||||
return doExpand(source, theOffset, theCount);
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, theUri, theFilter);
|
||||
return ValueSet40_50.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
|
||||
// for (UriType next : theSource.getCompose().getInclude()) {
|
||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||
// include.setSystem(next.getValue());
|
||||
// addFilterIfPresent(theFilter, include);
|
||||
// }
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet40_50.convertValueSet(theSource);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, canonicalInput, theFilter);
|
||||
return ValueSet40_50.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, String theFilter, int theOffset, int theCount) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
toExpand.setId(theSource.getId());
|
||||
toExpand.setUrl(theSource.getUrl());
|
||||
if (theSource.getVersion() != null) {
|
||||
toExpand.setVersion(theSource.getVersion());
|
||||
}
|
||||
|
||||
for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
addFilterIfPresent(theFilter, next);
|
||||
}
|
||||
|
||||
if (toExpand.getCompose().isEmpty()) {
|
||||
throw new InvalidRequestException("ValueSet does not have any compose.include or compose.import values, can not expand");
|
||||
}
|
||||
|
||||
toExpand.getCompose().getExclude().addAll(theSource.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand, theOffset, theCount);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void applyFilter(IntegerType theTotalElement, List<ValueSetExpansionContainsComponent> theContains, String theFilter) {
|
||||
|
||||
for (int idx = 0; idx < theContains.size(); idx++) {
|
||||
ValueSetExpansionContainsComponent next = theContains.get(idx);
|
||||
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
|
||||
theContains.remove(idx);
|
||||
idx--;
|
||||
if (theTotalElement.getValue() != null) {
|
||||
theTotalElement.setValue(theTotalElement.getValue() - 1);
|
||||
}
|
||||
}
|
||||
applyFilter(theTotalElement, next.getContains(), theFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
||||
if (ElementUtil.isEmpty(include.getConcept())) {
|
||||
if (isNotBlank(theFilter)) {
|
||||
include.addFilter().setProperty("display").setOp(Enumerations.FilterOperator.EQUAL).setValue(theFilter);
|
||||
}
|
||||
}
|
||||
ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet40_50.convertValueSet(theSource);
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, canonicalInput, theFilter);
|
||||
return ValueSet40_50.convertValueSet(canonicalOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -74,6 +74,7 @@ public class TermConcept implements Serializable {
|
|||
@Fields({
|
||||
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
||||
@Field(name = "myDisplayEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteEdgeAnalyzer")),
|
||||
@Field(name = "myDisplayWordEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteWordEdgeAnalyzer")),
|
||||
@Field(name = "myDisplayNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteNGramAnalyzer")),
|
||||
@Field(name = "myDisplayPhonetic", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompletePhoneticAnalyzer"))
|
||||
})
|
||||
|
|
|
@ -48,6 +48,12 @@ public class LuceneSearchMappingFactory {
|
|||
.filter(EdgeNGramFilterFactory.class)
|
||||
.param("minGramSize", "3")
|
||||
.param("maxGramSize", "50")
|
||||
.analyzerDef("autocompleteWordEdgeAnalyzer", StandardTokenizerFactory.class)
|
||||
.filter(LowerCaseFilterFactory.class)
|
||||
.filter(StopFilterFactory.class)
|
||||
.filter(EdgeNGramFilterFactory.class)
|
||||
.param("minGramSize", "2")
|
||||
.param("maxGramSize", "20")
|
||||
.analyzerDef("autocompletePhoneticAnalyzer", StandardTokenizerFactory.class)
|
||||
.filter(StandardFilterFactory.class)
|
||||
.filter(StopFilterFactory.class)
|
||||
|
|
|
@ -154,7 +154,7 @@ public class TokenPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
|||
*/
|
||||
|
||||
if (modifier == TokenParamModifier.IN) {
|
||||
codes.addAll(myTerminologySvc.expandValueSet(null, code));
|
||||
codes.addAll(myTerminologySvc.expandValueSetIntoConceptList(null, code));
|
||||
} else if (modifier == TokenParamModifier.ABOVE) {
|
||||
system = determineSystemIfMissing(theSearchParam, code, system);
|
||||
validateHaveSystemAndCodeForToken(paramName, code, system);
|
||||
|
@ -228,7 +228,7 @@ public class TokenPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
|||
String valueSet = valueSetUris.iterator().next();
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions()
|
||||
.setFailOnMissingCodeSystem(false);
|
||||
List<FhirVersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(options, valueSet);
|
||||
List<FhirVersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSetIntoConceptList(options, valueSet);
|
||||
for (FhirVersionIndependentConcept nextCandidate : candidateCodes) {
|
||||
if (nextCandidate.getCode().equals(code)) {
|
||||
retVal = nextCandidate.getSystem();
|
||||
|
|
|
@ -36,6 +36,14 @@ public class ElasticsearchMappingProvider implements ElasticsearchAnalysisDefini
|
|||
.param("min_gram", "3")
|
||||
.param("max_gram", "50");
|
||||
|
||||
builder.analyzer("autocompleteWordEdgeAnalyzer")
|
||||
.withTokenizer("standard")
|
||||
.withTokenFilters("lowercase", "stop", "wordedgengram_3_50");
|
||||
builder.tokenFilter("wordedgengram_3_50")
|
||||
.type("edgeNGram")
|
||||
.param("min_gram", "2")
|
||||
.param("max_gram", "20");
|
||||
|
||||
builder.analyzer("autocompletePhoneticAnalyzer")
|
||||
.withTokenizer("standard")
|
||||
.withTokenFilters("standard", "stop", "snowball_english");
|
||||
|
|
|
@ -67,6 +67,7 @@ import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
|||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||
|
@ -183,6 +184,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.lowerCase;
|
||||
|
||||
public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||
public static final int DEFAULT_FETCH_SIZE = 250;
|
||||
|
@ -394,25 +396,44 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
|
||||
@Override
|
||||
public List<FhirVersionIndependentConcept> expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet) {
|
||||
ExpansionFilter expansionFilter = ExpansionFilter.NO_FILTER;
|
||||
return expandValueSet(theExpansionOptions, theValueSet, expansionFilter);
|
||||
}
|
||||
|
||||
private List<FhirVersionIndependentConcept> expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet, ExpansionFilter theExpansionFilter) {
|
||||
@Transactional
|
||||
public List<FhirVersionIndependentConcept> expandValueSetIntoConceptList(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl) {
|
||||
String expansionFilter = null;
|
||||
// TODO: DM 2019-09-10 - This is problematic because an incorrect URL that matches ValueSet.id will not be found in the terminology tables but will yield a ValueSet here. Depending on the ValueSet, the expansion may time-out.
|
||||
|
||||
ValueSet valueSet = fetchCanonicalValueSetFromCompleteContext(theValueSet);
|
||||
ValueSet expanded = expandValueSet(theExpansionOptions, theValueSetCanonicalUrl, expansionFilter);
|
||||
|
||||
ArrayList<FhirVersionIndependentConcept> retVal = new ArrayList<>();
|
||||
for (ValueSet.ValueSetExpansionContainsComponent nextContains : expanded.getExpansion().getContains()) {
|
||||
retVal.add(new FhirVersionIndependentConcept(nextContains.getSystem(), nextContains.getCode(), nextContains.getDisplay(), nextContains.getVersion()));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl, @Nullable String theExpansionFilter) {
|
||||
ValueSet valueSet = fetchCanonicalValueSetFromCompleteContext(theValueSetCanonicalUrl);
|
||||
if (valueSet == null) {
|
||||
throwInvalidValueSet(theValueSet);
|
||||
throw new ResourceNotFoundException("Unknown ValueSet: " + UrlUtil.escapeUrlParam(theValueSetCanonicalUrl));
|
||||
}
|
||||
|
||||
return expandValueSetAndReturnVersionIndependentConcepts(theExpansionOptions, valueSet, theExpansionFilter);
|
||||
return expandValueSet(theExpansionOptions, valueSet, theExpansionFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public ValueSet expandValueSet(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand) {
|
||||
public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand) {
|
||||
return expandValueSet(theExpansionOptions, theValueSetToExpand, (String) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand, @Nullable String theFilter) {
|
||||
return expandValueSet(theExpansionOptions, theValueSetToExpand, ExpansionFilter.fromFilterString(theFilter));
|
||||
}
|
||||
|
||||
private ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, ExpansionFilter theFilter) {
|
||||
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSetToExpand, "ValueSet to expand can not be null");
|
||||
|
||||
ValueSetExpansionOptions expansionOptions = provideExpansionOptions(theExpansionOptions);
|
||||
|
@ -431,9 +452,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
accumulator.addParameter().setName("count").setValue(new IntegerType(count));
|
||||
}
|
||||
|
||||
ExpansionFilter filter = ExpansionFilter.NO_FILTER;
|
||||
|
||||
expandValueSetIntoAccumulator(theValueSetToExpand, theExpansionOptions, accumulator, filter, true);
|
||||
expandValueSetIntoAccumulator(theValueSetToExpand, theExpansionOptions, accumulator, theFilter, true);
|
||||
|
||||
if (accumulator.getTotalConcepts() != null) {
|
||||
accumulator.setTotal(accumulator.getTotalConcepts());
|
||||
|
@ -449,7 +469,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
.setUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE)
|
||||
.setValue(new StringType(next));
|
||||
}
|
||||
|
||||
return valueSet;
|
||||
}
|
||||
|
||||
|
@ -513,6 +532,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
boolean wasFilteredResult = false;
|
||||
if (!theFilter.getFilters().isEmpty() && JpaConstants.VALUESET_FILTER_DISPLAY.equals(theFilter.getFilters().get(0).getProperty()) && theFilter.getFilters().get(0).getOp() == ValueSet.FilterOperator.EQUAL) {
|
||||
String displayValue = theFilter.getFilters().get(0).getValue().replace("%", "[%]") + "%";
|
||||
displayValue = lowerCase(displayValue);
|
||||
conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theTermValueSet.getId(), displayValue);
|
||||
wasFilteredResult = true;
|
||||
} else {
|
||||
|
@ -675,7 +695,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
return theAction.get();
|
||||
}
|
||||
return myTxTemplate.execute(t->theAction.get());
|
||||
return myTxTemplate.execute(t -> theAction.get());
|
||||
}
|
||||
|
||||
private String getValueSetInfo(ValueSet theValueSet) {
|
||||
|
@ -702,18 +722,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
protected List<FhirVersionIndependentConcept> expandValueSetAndReturnVersionIndependentConcepts(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpandR4, @Nonnull ExpansionFilter theExpansionFilter) {
|
||||
int maxCapacity = myDaoConfig.getMaximumExpansionSize();
|
||||
ValueSetExpansionComponentWithConceptAccumulator accumulator = new ValueSetExpansionComponentWithConceptAccumulator(myContext, maxCapacity);
|
||||
expandValueSet(theExpansionOptions, theValueSetToExpandR4, accumulator, theExpansionFilter);
|
||||
|
||||
ArrayList<FhirVersionIndependentConcept> retVal = new ArrayList<>();
|
||||
for (org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent nextContains : accumulator.getContains()) {
|
||||
retVal.add(new FhirVersionIndependentConcept(nextContains.getSystem(), nextContains.getCode(), nextContains.getDisplay(), nextContains.getVersion()));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true if there are potentially more results to process.
|
||||
*/
|
||||
|
@ -938,12 +946,12 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
* DM 2019-08-21 - Processing slows after any ValueSets with many codes explicitly identified. This might
|
||||
* be due to the dark arts that is memory management. Will monitor but not do anything about this right now.
|
||||
*/
|
||||
BooleanQuery.setMaxClauseCount(10000);
|
||||
BooleanQuery.setMaxClauseCount(SearchBuilder.getMaximumPageSize());
|
||||
|
||||
StopWatch sw = new StopWatch();
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
int maxResultsPerBatch = 10000;
|
||||
int maxResultsPerBatch = SearchBuilder.getMaximumPageSize();
|
||||
|
||||
/*
|
||||
* If the accumulator is bounded, we may reduce the size of the query to
|
||||
|
@ -1083,8 +1091,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
.phrase()
|
||||
.withSlop(2)
|
||||
.onField("myDisplay").boostedTo(4.0f)
|
||||
.andField("myDisplayEdgeNGram").boostedTo(2.0f)
|
||||
// .andField("myDisplayNGram").boostedTo(1.0f)
|
||||
//.andField("myDisplayEdgeNGram").boostedTo(2.0f)
|
||||
.andField("myDisplayWordEdgeNGram").boostedTo(1.0f)
|
||||
// .andField("myDisplayPhonetic").boostedTo(0.5f)
|
||||
.sentence(nextFilter.getValue().toLowerCase()).createQuery();
|
||||
bool.must(textQuery);
|
||||
|
@ -1395,7 +1403,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
|
||||
return createFailureCodeValidationResult(theSystem, theCode, " - Concept Display \"" + theDisplay + "\" does not match expected \"" + concepts.get(0).getDisplay() + "\"").setDisplay(concepts.get(0).getDisplay());
|
||||
return createFailureCodeValidationResult(theSystem, theCode, " - Concept Display \"" + theDisplay + "\" does not match expected \"" + concepts.get(0).getDisplay() + "\"").setDisplay(concepts.get(0).getDisplay());
|
||||
}
|
||||
|
||||
if (!concepts.isEmpty()) {
|
||||
|
@ -1424,7 +1432,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
int versionIndex = theSystem.indexOf("|");
|
||||
if (versionIndex >= 0) {
|
||||
String systemUrl = theSystem.substring(0, versionIndex);
|
||||
String systemVersion = theSystem.substring(versionIndex+1);
|
||||
String systemVersion = theSystem.substring(versionIndex + 1);
|
||||
optionalTermValueSetConcept = myValueSetConceptDao.findByValueSetResourcePidSystemAndCodeWithVersion(theResourcePid.getIdAsLong(), systemUrl, systemVersion, theCode);
|
||||
} else {
|
||||
optionalTermValueSetConcept = myValueSetConceptDao.findByValueSetResourcePidSystemAndCode(theResourcePid.getIdAsLong(), theSystem, theCode);
|
||||
|
@ -1526,7 +1534,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
private String getUrlFromIdentifier(String theUri) {
|
||||
String retVal = theUri;
|
||||
if (StringUtils.isNotEmpty((theUri))){
|
||||
if (StringUtils.isNotEmpty((theUri))) {
|
||||
int versionSeparator = theUri.lastIndexOf('|');
|
||||
if (versionSeparator != -1) {
|
||||
retVal = theUri.substring(0, versionSeparator);
|
||||
|
@ -1781,9 +1789,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
} else {
|
||||
String msg = myContext.getLocalizer().getMessage(
|
||||
BaseTermReadSvcImpl.class,
|
||||
"cannotCreateDuplicateConceptMapUrlAndVersion",
|
||||
conceptMapUrl, conceptMapVersion,
|
||||
existingTermConceptMap.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
"cannotCreateDuplicateConceptMapUrlAndVersion",
|
||||
conceptMapUrl, conceptMapVersion,
|
||||
existingTermConceptMap.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
throw new UnprocessableEntityException(msg);
|
||||
}
|
||||
}
|
||||
|
@ -1818,7 +1826,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
// We have a ValueSet to pre-expand.
|
||||
try {
|
||||
ValueSet valueSet = txTemplate.execute(t -> {
|
||||
TermValueSet refreshedValueSetToExpand = myValueSetDao.findById(valueSetToExpand.getId()).orElseThrow(()->new IllegalStateException("Unknown VS ID: " + valueSetToExpand.getId()));
|
||||
TermValueSet refreshedValueSetToExpand = myValueSetDao.findById(valueSetToExpand.getId()).orElseThrow(() -> new IllegalStateException("Unknown VS ID: " + valueSetToExpand.getId()));
|
||||
return getValueSetFromResourceTable(refreshedValueSetToExpand.getResource());
|
||||
});
|
||||
assert valueSet != null;
|
||||
|
@ -1988,7 +1996,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
@Override
|
||||
@Transactional
|
||||
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB,
|
||||
IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
|
||||
IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
|
||||
FhirVersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
|
||||
FhirVersionIndependentConcept conceptB = toConcept(theCodeB, theSystem, theCodingB);
|
||||
|
||||
|
@ -2002,7 +2010,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
String codeASystemIdentifier;
|
||||
if (StringUtils.isNotEmpty(conceptA.getSystemVersion())) {
|
||||
codeASystemIdentifier = conceptA.getSystem() + "|" + conceptA.getSystemVersion();
|
||||
codeASystemIdentifier = conceptA.getSystem() + "|" + conceptA.getSystemVersion();
|
||||
} else {
|
||||
codeASystemIdentifier = conceptA.getSystem();
|
||||
}
|
||||
|
@ -2079,12 +2087,12 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
});
|
||||
}
|
||||
|
||||
private @Nullable
|
||||
ConceptSubsumptionOutcome testForSubsumption(FullTextEntityManager theEntityManager, TermConcept theLeft, TermConcept theRight, ConceptSubsumptionOutcome theOutput) {
|
||||
@Nullable
|
||||
private ConceptSubsumptionOutcome testForSubsumption(FullTextEntityManager theEntityManager, TermConcept theLeft, TermConcept theRight, ConceptSubsumptionOutcome theOutput) {
|
||||
QueryBuilder qb = theEntityManager.getSearchFactory().buildQueryBuilder().forEntity(TermConcept.class).get();
|
||||
BooleanJunction<?> bool = qb.bool();
|
||||
bool.must(qb.keyword().onField("myId").matching(Long.toString(theLeft.getId())).createQuery());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching(Long.toString(theRight.getId())).createQuery());
|
||||
bool.must(qb.keyword().onField("myId").matching(Long.toString(theRight.getId())).createQuery());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching(Long.toString(theLeft.getId())).createQuery());
|
||||
Query luceneQuery = bool.createQuery();
|
||||
FullTextQuery jpaQuery = theEntityManager.createFullTextQuery(luceneQuery, TermConcept.class);
|
||||
jpaQuery.setMaxResults(1);
|
||||
|
@ -2342,7 +2350,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
Pageable page = PageRequest.of(0, 1);
|
||||
List<TermConceptMap> theConceptMapList = myConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page,
|
||||
theTranslationRequest.getUrl().asStringValue());
|
||||
theTranslationRequest.getUrl().asStringValue());
|
||||
if (!theConceptMapList.isEmpty()) {
|
||||
return theConceptMapList.get(0).getVersion();
|
||||
}
|
||||
|
@ -2553,6 +2561,136 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
@Nullable
|
||||
protected abstract CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept);
|
||||
|
||||
@NotNull
|
||||
private FhirVersionIndependentConcept toConcept(IPrimitiveType<String> theCodeType, IPrimitiveType<String> theCodeSystemIdentifierType, IBaseCoding theCodingType) {
|
||||
String code = theCodeType != null ? theCodeType.getValueAsString() : null;
|
||||
String system = theCodeSystemIdentifierType != null ? getUrlFromIdentifier(theCodeSystemIdentifierType.getValueAsString()) : null;
|
||||
String systemVersion = theCodeSystemIdentifierType != null ? getVersionFromIdentifier(theCodeSystemIdentifierType.getValueAsString()) : null;
|
||||
if (theCodingType != null) {
|
||||
Coding canonicalizedCoding = toCanonicalCoding(theCodingType);
|
||||
assert canonicalizedCoding != null; // Shouldn't be null, since theCodingType isn't
|
||||
code = canonicalizedCoding.getCode();
|
||||
system = canonicalizedCoding.getSystem();
|
||||
systemVersion = canonicalizedCoding.getVersion();
|
||||
}
|
||||
return new FhirVersionIndependentConcept(system, code, null, systemVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theCodeSystemUrl, String theVersion, 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 (code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
boolean haveIdentifierParam = isNotBlank(theCodeSystemUrl);
|
||||
String codeSystemUrl;
|
||||
if (theCodeSystemId != null) {
|
||||
IBaseResource codeSystem = myDaoRegistry.getResourceDao("CodeSystem").read(theCodeSystemId);
|
||||
codeSystemUrl = CommonCodeSystemsTerminologyService.getCodeSystemUrl(codeSystem);
|
||||
} else if (haveIdentifierParam) {
|
||||
codeSystemUrl = theCodeSystemUrl;
|
||||
} else {
|
||||
throw new InvalidRequestException("Either CodeSystem ID or CodeSystem identifier must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
|
||||
String code = theCode;
|
||||
String display = theDisplay;
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
if (nextCoding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(nextCoding.getSystem())) {
|
||||
throw new InvalidRequestException("Coding.system '" + nextCoding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = nextCoding.getSystem();
|
||||
}
|
||||
code = nextCoding.getCode();
|
||||
display = nextCoding.getDisplay();
|
||||
CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
} else if (haveCoding) {
|
||||
if (coding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(coding.getSystem())) {
|
||||
throw new InvalidRequestException("Coding.system '" + coding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = coding.getSystem();
|
||||
}
|
||||
code = coding.getCode();
|
||||
display = coding.getDisplay();
|
||||
}
|
||||
|
||||
return codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CodeValidationResult codeSystemValidateCode(String theCodeSystemUrl, String theCodeSystemVersion, String theCode, String theDisplay) {
|
||||
|
||||
CriteriaBuilder criteriaBuilder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<TermConcept> query = criteriaBuilder.createQuery(TermConcept.class);
|
||||
Root<TermConcept> root = query.from(TermConcept.class);
|
||||
|
||||
Fetch<TermCodeSystemVersion, TermConcept> systemVersionFetch = root.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystemVersion, TermConcept> systemVersionJoin = (Join<TermCodeSystemVersion, TermConcept>) systemVersionFetch;
|
||||
Fetch<TermCodeSystem, TermCodeSystemVersion> systemFetch = systemVersionFetch.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystem, TermCodeSystemVersion> systemJoin = (Join<TermCodeSystem, TermCodeSystemVersion>) systemFetch;
|
||||
|
||||
ArrayList<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
if (isNotBlank(theCode)) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("myCode"), theCode));
|
||||
}
|
||||
|
||||
if (isNotBlank(theDisplay)) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("myDisplay"), theDisplay));
|
||||
}
|
||||
|
||||
if (isNoneBlank(theCodeSystemUrl)) {
|
||||
predicates.add(criteriaBuilder.equal(systemJoin.get("myCodeSystemUri"), theCodeSystemUrl));
|
||||
}
|
||||
|
||||
if (isNoneBlank(theCodeSystemVersion)) {
|
||||
predicates.add(criteriaBuilder.equal(systemVersionJoin.get("myCodeSystemVersionId"), theCodeSystemVersion));
|
||||
} else {
|
||||
query.orderBy(criteriaBuilder.desc(root.get("myUpdated")));
|
||||
}
|
||||
|
||||
Predicate outerPredicate = criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||
query.where(outerPredicate);
|
||||
|
||||
final TypedQuery<TermConcept> typedQuery = myEntityManager.createQuery(query.select(root));
|
||||
org.hibernate.query.Query<TermConcept> hibernateQuery = (org.hibernate.query.Query<TermConcept>) typedQuery;
|
||||
hibernateQuery.setFetchSize(SINGLE_FETCH_SIZE);
|
||||
List<TermConcept> resultsList = hibernateQuery.getResultList();
|
||||
|
||||
if (!resultsList.isEmpty()) {
|
||||
TermConcept concept = resultsList.get(0);
|
||||
return new CodeValidationResult().setCode(concept.getCode()).setDisplay(concept.getDisplay());
|
||||
}
|
||||
|
||||
if (isBlank(theDisplay))
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode);
|
||||
else
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, " - Concept Display : " + theDisplay);
|
||||
}
|
||||
|
||||
public static class Job implements HapiJob {
|
||||
@Autowired
|
||||
private ITermReadSvc myTerminologySvc;
|
||||
|
@ -2640,21 +2778,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
return termConcept;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private FhirVersionIndependentConcept toConcept(IPrimitiveType<String> theCodeType, IPrimitiveType<String> theCodeSystemIdentifierType, IBaseCoding theCodingType) {
|
||||
String code = theCodeType != null ? theCodeType.getValueAsString() : null;
|
||||
String system = theCodeSystemIdentifierType != null ? getUrlFromIdentifier(theCodeSystemIdentifierType.getValueAsString()): null;
|
||||
String systemVersion = theCodeSystemIdentifierType != null ? getVersionFromIdentifier(theCodeSystemIdentifierType.getValueAsString()): null;
|
||||
if (theCodingType != null) {
|
||||
Coding canonicalizedCoding = toCanonicalCoding(theCodingType);
|
||||
assert canonicalizedCoding != null; // Shouldn't be null, since theCodingType isn't
|
||||
code = canonicalizedCoding.getCode();
|
||||
system = canonicalizedCoding.getSystem();
|
||||
systemVersion = canonicalizedCoding.getVersion();
|
||||
}
|
||||
return new FhirVersionIndependentConcept(system, code, null, systemVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is present only for unit tests, do not call from client code
|
||||
*/
|
||||
|
@ -2686,120 +2809,4 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
static boolean isOurLastResultsFromTranslationWithReverseCache() {
|
||||
return ourLastResultsFromTranslationWithReverseCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theCodeSystemUrl, String theVersion, 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 (code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
boolean haveIdentifierParam = isNotBlank(theCodeSystemUrl);
|
||||
String codeSystemUrl;
|
||||
if (theCodeSystemId != null) {
|
||||
IBaseResource codeSystem = myDaoRegistry.getResourceDao("CodeSystem").read(theCodeSystemId);
|
||||
codeSystemUrl = CommonCodeSystemsTerminologyService.getCodeSystemUrl(codeSystem);
|
||||
} else if (haveIdentifierParam) {
|
||||
codeSystemUrl = theCodeSystemUrl;
|
||||
} else {
|
||||
throw new InvalidRequestException("Either CodeSystem ID or CodeSystem identifier must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
|
||||
String code = theCode;
|
||||
String display = theDisplay;
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
if (nextCoding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(nextCoding.getSystem())) {
|
||||
throw new InvalidRequestException("Coding.system '" + nextCoding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = nextCoding.getSystem();
|
||||
}
|
||||
code = nextCoding.getCode();
|
||||
display = nextCoding.getDisplay();
|
||||
CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
} else if (haveCoding) {
|
||||
if (coding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(coding.getSystem())) {
|
||||
throw new InvalidRequestException("Coding.system '" + coding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = coding.getSystem();
|
||||
}
|
||||
code = coding.getCode();
|
||||
display = coding.getDisplay();
|
||||
}
|
||||
|
||||
return codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CodeValidationResult codeSystemValidateCode(String theCodeSystemUrl, String theCodeSystemVersion, String theCode, String theDisplay) {
|
||||
|
||||
CriteriaBuilder criteriaBuilder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<TermConcept> query = criteriaBuilder.createQuery(TermConcept.class);
|
||||
Root<TermConcept> root = query.from(TermConcept.class);
|
||||
|
||||
Fetch<TermCodeSystemVersion, TermConcept> systemVersionFetch = root.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystemVersion, TermConcept> systemVersionJoin = (Join<TermCodeSystemVersion, TermConcept>)systemVersionFetch;
|
||||
Fetch<TermCodeSystem, TermCodeSystemVersion> systemFetch = systemVersionFetch.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystem, TermCodeSystemVersion> systemJoin = (Join<TermCodeSystem, TermCodeSystemVersion>)systemFetch;
|
||||
|
||||
ArrayList<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
if (isNotBlank(theCode)) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("myCode"), theCode));
|
||||
}
|
||||
|
||||
if (isNotBlank(theDisplay)) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("myDisplay"), theDisplay));
|
||||
}
|
||||
|
||||
if (isNoneBlank(theCodeSystemUrl)) {
|
||||
predicates.add(criteriaBuilder.equal(systemJoin.get("myCodeSystemUri"), theCodeSystemUrl));
|
||||
}
|
||||
|
||||
if (isNoneBlank(theCodeSystemVersion)) {
|
||||
predicates.add(criteriaBuilder.equal(systemVersionJoin.get("myCodeSystemVersionId"), theCodeSystemVersion));
|
||||
} else {
|
||||
query.orderBy(criteriaBuilder.desc(root.get("myUpdated")));
|
||||
}
|
||||
|
||||
Predicate outerPredicate = criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||
query.where(outerPredicate);
|
||||
|
||||
final TypedQuery<TermConcept> typedQuery = myEntityManager.createQuery(query.select(root));
|
||||
org.hibernate.query.Query<TermConcept> hibernateQuery = (org.hibernate.query.Query<TermConcept>) typedQuery;
|
||||
hibernateQuery.setFetchSize(SINGLE_FETCH_SIZE);
|
||||
List<TermConcept> resultsList = hibernateQuery.getResultList();
|
||||
|
||||
if (!resultsList.isEmpty()) {
|
||||
TermConcept concept = resultsList.get(0);
|
||||
return new CodeValidationResult().setCode(concept.getCode()).setDisplay(concept.getDisplay());
|
||||
}
|
||||
|
||||
if (isBlank(theDisplay))
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode);
|
||||
else
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, " - Concept Display : " + theDisplay);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.term;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.util.FhirVersionIndependentConcept;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
@ -29,6 +30,7 @@ import javax.annotation.Nullable;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
class ExpansionFilter {
|
||||
|
@ -95,4 +97,19 @@ class ExpansionFilter {
|
|||
public Integer getMaxCount() {
|
||||
return myMaxCount;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ExpansionFilter fromFilterString(@Nullable String theFilter) {
|
||||
ExpansionFilter filter;
|
||||
if (isNoneBlank(theFilter)) {
|
||||
List<ValueSet.ConceptSetFilterComponent> filters = Collections.singletonList(new ValueSet.ConceptSetFilterComponent()
|
||||
.setProperty(JpaConstants.VALUESET_FILTER_DISPLAY)
|
||||
.setOp(ValueSet.FilterOperator.EQUAL)
|
||||
.setValue(theFilter));
|
||||
filter = new ExpansionFilter(null, null, filters, null);
|
||||
} else {
|
||||
filter = ExpansionFilter.NO_FILTER;
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.term;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||
import ca.uhn.fhir.model.api.annotation.Block;
|
||||
|
@ -45,6 +46,15 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
|
|||
private int myAddedConcepts;
|
||||
private Integer myTotalConcepts;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theDaoConfig Will be used to determine the max capacity for this accumulator
|
||||
*/
|
||||
public ValueSetExpansionComponentWithConceptAccumulator(FhirContext theContext, DaoConfig theDaoConfig) {
|
||||
this(theContext, theDaoConfig.getMaximumExpansionSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -56,7 +66,7 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Integer getCapacityRemaining() {
|
||||
return (myMaxCapacity - myAddedConcepts) + mySkipCountRemaining;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hl7.fhir.r4.model.CodeSystem;
|
|||
import org.hl7.fhir.r4.model.ConceptMap;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
@ -57,7 +58,11 @@ import java.util.Set;
|
|||
*/
|
||||
public interface ITermReadSvc extends IValidationSupport {
|
||||
|
||||
ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand);
|
||||
ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl, @Nullable String theExpansionFilter);
|
||||
|
||||
ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand);
|
||||
|
||||
ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand, @Nullable String theFilter);
|
||||
|
||||
void expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator);
|
||||
|
||||
|
@ -68,7 +73,7 @@ public interface ITermReadSvc extends IValidationSupport {
|
|||
|
||||
void expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator);
|
||||
|
||||
List<FhirVersionIndependentConcept> expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet);
|
||||
List<FhirVersionIndependentConcept> expandValueSetIntoConceptList(ValueSetExpansionOptions theExpansionOptions, String theValueSetCanonicalUrl);
|
||||
|
||||
Optional<TermConcept> findCode(String theCodeSystem, String theCode);
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ import static org.apache.commons.lang3.StringUtils.trim;
|
|||
|
||||
public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implements IRecordHandler {
|
||||
|
||||
public static final String LOINC_IEEE_CM_ID = "loinc-to-ieee-device-codes";
|
||||
public static final String LOINC_IEEE_CM_URI = "http://loinc.org/cm/loinc-to-ieee-device-codes";
|
||||
public static final String LOINC_IEEE_CM_ID = "loinc-to-ieee-11073-10101";
|
||||
public static final String LOINC_IEEE_CM_URI = "http://loinc.org/cm/loinc-to-ieee-11073-10101";
|
||||
public static final String LOINC_IEEE_CM_NAME = "LOINC/IEEE Device Code Mappings";
|
||||
private static final String CM_COPYRIGHT = "This content from LOINC® is copyright © 1995 Regenstrief Institute, Inc. and the LOINC Committee, and available at no cost under the license at https://loinc.org/license/. The LOINC/IEEE Medical Device Code Mapping Table contains content from IEEE (http://ieee.org), copyright © 2017 IEEE.";
|
||||
|
||||
|
|
|
@ -42,11 +42,11 @@ public class LoincPartRelatedCodeMappingHandler extends BaseLoincHandler impleme
|
|||
|
||||
public static final String LOINC_SCT_PART_MAP_ID = "loinc-parts-to-snomed-ct";
|
||||
public static final String LOINC_SCT_PART_MAP_URI = "http://loinc.org/cm/loinc-parts-to-snomed-ct";
|
||||
public static final String LOINC_TERM_TO_RPID_PART_MAP_ID = "loinc-to-rpids";
|
||||
public static final String LOINC_TERM_TO_RPID_PART_MAP_URI = "http://loinc.org/cm/loinc-to-rpids";
|
||||
public static final String LOINC_TERM_TO_RPID_PART_MAP_ID = "loinc-to-radlex";
|
||||
public static final String LOINC_TERM_TO_RPID_PART_MAP_URI = "http://loinc.org/cm/loinc-to-radlex";
|
||||
public static final String LOINC_TERM_TO_RPID_PART_MAP_NAME = "LOINC Terms to RadLex RPIDs";
|
||||
public static final String LOINC_PART_TO_RID_PART_MAP_ID = "loinc-part-to-rids";
|
||||
public static final String LOINC_PART_TO_RID_PART_MAP_URI = "http://loinc.org/cm/loinc-part-to-rids";
|
||||
public static final String LOINC_PART_TO_RID_PART_MAP_ID = "loinc-parts-to-radlex";
|
||||
public static final String LOINC_PART_TO_RID_PART_MAP_URI = "http://loinc.org/cm/loinc-parts-to-radlex";
|
||||
public static final String LOINC_PART_TO_RID_PART_MAP_NAME = "LOINC Parts to RadLex RIDs";
|
||||
private static final String LOINC_SCT_PART_MAP_NAME = "LOINC Part Map to SNOMED CT";
|
||||
private static final String LOINC_RXNORM_PART_MAP_ID = "loinc-parts-to-rxnorm";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import net.ttddyy.dsproxy.ExecutionInfo;
|
||||
import net.ttddyy.dsproxy.QueryInfo;
|
||||
import net.ttddyy.dsproxy.proxy.ParameterSetOperation;
|
||||
|
|
|
@ -139,7 +139,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
|
|||
myPatientDao.create(p);
|
||||
} catch (PreconditionFailedException e) {
|
||||
// expected - This is as a result of the unique SP
|
||||
assertThat(e.getMessage(), containsString("duplicate index matching query: Patient?gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(e.getMessage(), containsString("duplicate unique index matching query: Patient?gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
} catch (ResourceVersionConflictException e) {
|
||||
// expected - This is as a result of the unique SP
|
||||
assertThat(e.getMessage(), containsString("would have resulted in a duplicate value for a unique index"));
|
||||
|
|
|
@ -1,5 +1,36 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
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.Meta;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.hl7.fhir.r4.model.Quantity;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
|
@ -24,38 +55,8 @@ import ca.uhn.fhir.parser.IParser;
|
|||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
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.Meta;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.hl7.fhir.r4.model.Quantity;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {TestR4ConfigWithElasticSearch.class})
|
||||
|
@ -155,11 +156,63 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest {
|
|||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandWithFilter() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, "child");
|
||||
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<code value=\"childCA\"/>","<display value=\"Child CA\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithFilterContainsLeftMatchingValue() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, "chi");
|
||||
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<code value=\"childCA\"/>","<display value=\"Child CA\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithFilterContainsNotLeftMatchingValue() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, "hil");
|
||||
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"childCA\"/>","<display value=\"Child CA\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandVsWithMultiInclude_All() throws IOException {
|
||||
CodeSystem cs = loadResource(myFhirCtx, CodeSystem.class, "/r4/expand-multi-cs.json");
|
||||
|
@ -271,7 +324,6 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
private void logAndValidateValueSet(ValueSet theResult) {
|
||||
IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = parser.encodeResourceToString(theResult);
|
||||
|
|
|
@ -803,7 +803,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertEquals("Can not create resource of type Patient as it would create a duplicate index matching query: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale (existing index belongs to Patient/" + id1.getIdPart() + ")", e.getMessage());
|
||||
assertEquals("Can not create resource of type Patient as it would create a duplicate unique index matching query: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale (existing index belongs to Patient/" + id1.getIdPart() + ", new unique index created by SearchParameter/patient-gender-birthdate)", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1510,7 +1510,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
// good
|
||||
assertThat(e.getMessage(), containsString("new unique index created by SearchParameter/patient-gender-birthdate"));
|
||||
}
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
|
@ -1525,7 +1525,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myPatientDao.update(pt2);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
// good
|
||||
assertThat(e.getMessage(), containsString("new unique index created by SearchParameter/patient-gender-birthdate"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -423,8 +423,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -440,8 +440,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentC"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("1"))
|
||||
.execute();
|
||||
|
@ -458,8 +458,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("2"))
|
||||
.execute();
|
||||
|
@ -480,8 +480,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -497,8 +497,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentC"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("1"))
|
||||
.execute();
|
||||
|
@ -515,8 +515,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("2"))
|
||||
.execute();
|
||||
|
@ -610,8 +610,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -626,8 +626,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -642,8 +642,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -663,8 +663,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -679,8 +679,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -695,8 +695,8 @@ public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourcePr
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
|
|
@ -50,6 +50,8 @@ import java.util.List;
|
|||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM;
|
||||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest.URL_MY_VALUE_SET;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
@ -343,14 +345,14 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, Matchers.containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, Matchers.not(Matchers.containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -857,6 +859,68 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("blo"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("lood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("loood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByUrlWithFilter() throws Exception {
|
||||
loadAndPersistCodeSystemAndValueSet();
|
||||
|
@ -866,7 +930,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
|
||||
.andParameter("filter", new StringType("first"))
|
||||
.andParameter("filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
|
|
|
@ -385,28 +385,28 @@ public class ResourceProviderDstu3ValueSetVersionedTest extends BaseResourceProv
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
// Verify ValueSet v2
|
||||
respParam = ourClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -425,28 +425,28 @@ public class ResourceProviderDstu3ValueSetVersionedTest extends BaseResourceProv
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
// Validate ValueSet v2
|
||||
respParam = ourClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -274,8 +274,8 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ChildAA"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ChildAA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -294,8 +294,8 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ChildAA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ChildAA"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -381,8 +381,8 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -400,8 +400,8 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
|
|
@ -445,8 +445,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -462,8 +462,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentC"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("1"))
|
||||
.execute();
|
||||
|
@ -480,8 +480,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("2"))
|
||||
.execute();
|
||||
|
@ -502,8 +502,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -519,8 +519,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentC"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("1"))
|
||||
.execute();
|
||||
|
@ -537,8 +537,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("2"))
|
||||
.execute();
|
||||
|
@ -632,8 +632,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -648,8 +648,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -664,8 +664,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -685,8 +685,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -701,8 +701,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
@ -717,8 +717,8 @@ public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
|
|
@ -287,14 +287,14 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -312,14 +312,14 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1194,6 +1194,68 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("blo"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("lood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
|
||||
loadAndPersistCodeSystem();
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("loood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByUrlWithFilter() throws Exception {
|
||||
loadAndPersistCodeSystemAndValueSet();
|
||||
|
@ -1203,7 +1265,7 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
|
|||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
|
||||
.andParameter("filter", new StringType("first"))
|
||||
.andParameter("filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
|
|
|
@ -261,14 +261,14 @@ public class ResourceProviderR4ValueSetVerCSNoVerTest extends BaseResourceProvid
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -286,14 +286,14 @@ public class ResourceProviderR4ValueSetVerCSNoVerTest extends BaseResourceProvid
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||
|
@ -11,8 +12,11 @@ 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.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
@ -37,6 +41,7 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
|
@ -44,7 +49,9 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
|
@ -331,28 +338,28 @@ public class ResourceProviderR4ValueSetVerCSVerTest extends BaseResourceProvider
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
// Verify ValueSet v2
|
||||
respParam = myClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -372,28 +379,27 @@ public class ResourceProviderR4ValueSetVerCSVerTest extends BaseResourceProvider
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
|
||||
// Validate ValueSet v2
|
||||
respParam = myClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -102,8 +102,8 @@ public class ResourceProviderR5CodeSystemTest extends BaseResourceProviderR5Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ChildAA"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ChildAA"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -121,8 +121,8 @@ public class ResourceProviderR5CodeSystemTest extends BaseResourceProviderR5Test
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
|
||||
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
|
|
|
@ -220,8 +220,8 @@ public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.execute();
|
||||
|
||||
|
@ -237,8 +237,8 @@ public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentC"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("1"))
|
||||
.execute();
|
||||
|
@ -255,8 +255,8 @@ public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProvi
|
|||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_SUBSUMES)
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
|
||||
.andParameter("codeB", new CodeType("ParentA"))
|
||||
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
|
||||
.andParameter("codeB", new CodeType("ParentB"))
|
||||
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
|
||||
.andParameter("version", new StringType("2"))
|
||||
.execute();
|
||||
|
|
|
@ -70,7 +70,6 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
private IIdType myExtensionalCsId;
|
||||
private IIdType myExtensionalVsId;
|
||||
private IIdType myLocalValueSetId;
|
||||
private Long myExtensionalCsIdOnResourceTable;
|
||||
private Long myExtensionalVsIdOnResourceTable;
|
||||
private ValueSet myLocalVs;
|
||||
|
||||
|
@ -84,11 +83,6 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
loadAndPersistValueSet(theVerb);
|
||||
}
|
||||
|
||||
private void loadAndPersistCodeSystemAndValueSetWithDesignationsAndExclude(HTTPVerb theVerb) throws IOException {
|
||||
loadAndPersistCodeSystemWithDesignations(theVerb);
|
||||
loadAndPersistValueSetWithExclude(theVerb);
|
||||
}
|
||||
|
||||
private void loadAndPersistCodeSystem(HTTPVerb theVerb) throws IOException {
|
||||
CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
|
||||
codeSystem.setId("CodeSystem/cs");
|
||||
|
@ -123,7 +117,6 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
default:
|
||||
throw new IllegalArgumentException("HTTP verb is not supported: " + theVerb);
|
||||
}
|
||||
myExtensionalCsIdOnResourceTable = myCodeSystemDao.readEntity(myExtensionalCsId, null).getId();
|
||||
}
|
||||
|
||||
private void loadAndPersistValueSet(HTTPVerb theVerb) throws IOException {
|
||||
|
@ -132,12 +125,6 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
persistValueSet(valueSet, theVerb);
|
||||
}
|
||||
|
||||
private void loadAndPersistValueSetWithExclude(HTTPVerb theVerb) throws IOException {
|
||||
ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs-with-exclude.xml");
|
||||
valueSet.setId("ValueSet/vs");
|
||||
persistValueSet(valueSet, theVerb);
|
||||
}
|
||||
|
||||
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
|
||||
private void persistValueSet(ValueSet theValueSet, HTTPVerb theVerb) {
|
||||
switch (theVerb) {
|
||||
|
@ -404,14 +391,14 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -426,14 +413,14 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1440,6 +1427,68 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem(HTTPVerb.POST);
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("blo"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
|
||||
loadAndPersistCodeSystem(HTTPVerb.POST);
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("lood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
|
||||
loadAndPersistCodeSystem(HTTPVerb.POST);
|
||||
|
||||
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
|
||||
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "valueSet", toExpand)
|
||||
.andParameter("filter", new StringType("loood"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByUrlWithFilter() throws Exception {
|
||||
loadAndPersistCodeSystemAndValueSet(HTTPVerb.POST);
|
||||
|
@ -1449,7 +1498,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
|
|||
.onType(ValueSet.class)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
|
||||
.andParameter("filter", new StringType("first"))
|
||||
.andParameter("filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
|
|
|
@ -368,28 +368,28 @@ public class ResourceProviderR5ValueSetVersionedTest extends BaseResourceProvide
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
// Verify ValueSet v2
|
||||
respParam = myClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
@ -409,28 +409,28 @@ public class ResourceProviderR5ValueSetVersionedTest extends BaseResourceProvide
|
|||
.operation()
|
||||
.onInstance(myExtensionalVsId_v1)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
// Validate ValueSet v2
|
||||
respParam = myClient
|
||||
.operation()
|
||||
.onInstance(myExtensionalVsId_v2)
|
||||
.named("expand")
|
||||
.withParameter(Parameters.class, "filter", new StringType("first"))
|
||||
.withParameter(Parameters.class, "filter", new StringType("systolic"))
|
||||
.execute();
|
||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter v2\"/>"));
|
||||
assertThat(resp, not(containsString("<display value=\"Systolic blood pressure--expiration v2\"/>")));
|
||||
assertThat(resp, not(containsString("\"Foo Code\"")));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
|||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -22,10 +23,12 @@ import org.hl7.fhir.r4.model.CodeSystem;
|
|||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r4.model.codesystems.HttpVerb;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
@ -60,6 +63,11 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
@Mock
|
||||
private IValueSetConceptAccumulator myValueSetCodeAccumulator;
|
||||
|
||||
@AfterEach
|
||||
public void afterEach() {
|
||||
SearchBuilder.setMaxPageSize50ForTest(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePreExpandedValueSet() throws IOException {
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
|
@ -181,7 +189,53 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'"));
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 9%'"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandHugeValueSet_FilterOnDisplay_LeftMatch_SelectAll() {
|
||||
SearchBuilder.setMaxPageSize50ForTest(true);
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
IIdType vsId = createConceptsCodeSystemAndValueSet(1005);
|
||||
|
||||
// Inline ValueSet
|
||||
{
|
||||
ValueSet input = new ValueSet();
|
||||
input.getCompose()
|
||||
.addInclude()
|
||||
.addValueSet("http://foo/vs")
|
||||
.addFilter()
|
||||
.setProperty(JpaConstants.VALUESET_FILTER_DISPLAY)
|
||||
.setOp(ValueSet.FilterOperator.EQUAL)
|
||||
.setValue("display value 100");
|
||||
|
||||
// Expansion should contain all codes
|
||||
myCaptureQueriesListener.clear();
|
||||
ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input);
|
||||
List<String> codes = expandedValueSet.getExpansion().getContains().stream().map(t -> t.getCode()).collect(Collectors.toList());
|
||||
assertThat(codes.toString(), codes, contains("code100", "code1000", "code1001", "code1002", "code1003", "code1004"));
|
||||
|
||||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
ourLog.info("SQL: {}", lastSelectQuery);
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 100%'"));
|
||||
}
|
||||
|
||||
// ValueSet by ID
|
||||
{
|
||||
myCaptureQueriesListener.clear();
|
||||
ValueSet expandedValueSet = myValueSetDao.expand(vsId, "display value 100", 0, 1000, mySrd);
|
||||
List<String> codes = expandedValueSet.getExpansion().getContains().stream().map(t -> t.getCode()).collect(Collectors.toList());
|
||||
assertThat(codes.toString(), codes, contains("code100", "code1000", "code1001", "code1002", "code1003", "code1004"));
|
||||
|
||||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
ourLog.info("SQL: {}", lastSelectQuery);
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 100%'"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -215,11 +269,38 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'"));
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 9%'"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandInline_IncludePreExpandedValueSetByUri_FilterOnDisplay_LeftMatchCaseInsensitive() {
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
create100ConceptsCodeSystemAndValueSet();
|
||||
|
||||
ValueSet input = new ValueSet();
|
||||
input.getCompose()
|
||||
.addInclude()
|
||||
.addValueSet("http://foo/vs")
|
||||
.addFilter()
|
||||
.setProperty(JpaConstants.VALUESET_FILTER_DISPLAY)
|
||||
.setOp(ValueSet.FilterOperator.EQUAL)
|
||||
.setValue("dIsPlAy valuE 99");
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
ValueSet expandedValueSet = myTermSvc.expandValueSet(null, input);
|
||||
ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet));
|
||||
|
||||
assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( "code99" ));
|
||||
|
||||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
assertThat(lastSelectQuery, containsString("like 'display value 99%'"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandInline_IncludePreExpandedValueSetByUri_ExcludeCodes_FilterOnDisplay_LeftMatch_SelectAll() {
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
|
@ -254,7 +335,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
assertThat(lastSelectQuery, containsString("concept_display like 'display value 90%'"));
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 90%'"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -292,24 +373,38 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void create100ConceptsCodeSystemAndValueSet() {
|
||||
createConceptsCodeSystemAndValueSet(100);
|
||||
}
|
||||
|
||||
public IIdType createConceptsCodeSystemAndValueSet(int theCount) {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo/cs");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CustomTerminologySet additions = new CustomTerminologySet();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (int i = 0; i < theCount; i++) {
|
||||
additions.addRootConcept("code" + i, "display value " + i);
|
||||
}
|
||||
myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", additions);
|
||||
myTerminologyDeferredStorageSvc.saveAllDeferred();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl("http://foo/vs");
|
||||
vs.getCompose().addInclude().setSystem("http://foo/cs");
|
||||
myValueSetDao.create(vs);
|
||||
IIdType vsId = myValueSetDao.create(vs).getId().toUnqualifiedVersionless();
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
|
||||
// Confirm we pre-expanded successfully
|
||||
runInTransaction(() -> {
|
||||
Pageable page = Pageable.unpaged();
|
||||
List<TermValueSet> valueSets = myTermValueSetDao.findTermValueSetByUrl(page, "http://foo/vs");
|
||||
assertEquals(1, valueSets.size());
|
||||
assertEquals(TermValueSetPreExpansionStatusEnum.EXPANDED, valueSets.get(0).getExpansionStatus());
|
||||
});
|
||||
|
||||
return vsId;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -339,7 +434,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
// Make sure we used the pre-expanded version
|
||||
List<SqlQuery> selectQueries = myCaptureQueriesListener.getSelectQueries();
|
||||
String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase();
|
||||
assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'"));
|
||||
assertThat(lastSelectQuery, containsString(" like 'display value 9%'"));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
|
@ -89,12 +89,12 @@
|
|||
<code value="8490-5" />
|
||||
<display value="Systolic blood pressure 24 hour mean" />
|
||||
</concept>
|
||||
<concept>
|
||||
<code value="8491-3" />
|
||||
<display value="Systolic blood pressure 1 hour minimum" />
|
||||
</concept>
|
||||
<concept>
|
||||
<code value="8492-1" />
|
||||
<display value="Systolic blood pressure 8 hour minimum" />
|
||||
</concept>
|
||||
<concept>
|
||||
<code value="9999-9" />
|
||||
<display value="Foo Code" />
|
||||
</concept>
|
||||
</CodeSystem>
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
|||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -59,6 +60,8 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
@SuppressWarnings("unused")
|
||||
@Column(name = PartitionablePartitionId.PARTITION_ID, insertable = false, updatable = false, nullable = true)
|
||||
private Integer myPartitionIdValue;
|
||||
@Transient
|
||||
private IIdType mySearchParameterId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -70,10 +73,11 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString) {
|
||||
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString, IIdType theSearchParameterId) {
|
||||
setResource(theResource);
|
||||
setIndexString(theIndexString);
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
setSearchParameterId(theSearchParameterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,4 +135,18 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
.append("partition", getPartitionId())
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: This field is not persisted, so it will only be populated for new indexes
|
||||
*/
|
||||
public void setSearchParameterId(IIdType theSearchParameterId) {
|
||||
mySearchParameterId = theSearchParameterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: This field is not persisted, so it will only be populated for new indexes
|
||||
*/
|
||||
public IIdType getSearchParameterId() {
|
||||
return mySearchParameterId;
|
||||
}
|
||||
}
|
||||
|
|
7
pom.xml
7
pom.xml
|
@ -684,6 +684,11 @@
|
|||
<id>blangley28</id>
|
||||
<organization>MITRE</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>swagers</id>
|
||||
<name>Steven Wagers</name>
|
||||
<organization>Regenstrief Institute</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
|
@ -733,7 +738,7 @@
|
|||
<jena_version>3.16.0</jena_version>
|
||||
<jersey_version>2.25.1</jersey_version>
|
||||
<!-- 9.4.17 seems to have issues -->
|
||||
<jetty_version>9.4.30.v20200611</jetty_version>
|
||||
<jetty_version>9.4.34.v20201102</jetty_version>
|
||||
<jsr305_version>3.0.2</jsr305_version>
|
||||
<junit_version>5.6.2</junit_version>
|
||||
<flyway_version>6.5.4</flyway_version>
|
||||
|
|
Loading…
Reference in New Issue