Make quantity indexes use double datatype (#2290)
* Make quantity indexes use double datatype * Add changelog * Test fixes * Test fixes * Disable test
This commit is contained in:
parent
24ac055b50
commit
1dc4fb2206
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.rest.param;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
@ -301,4 +302,22 @@ public class QuantityParam extends BaseParamWithPrefix<QuantityParam> implements
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static QuantityParam toQuantityParam(IQueryParameterType theParam) {
|
||||||
|
if (theParam instanceof BaseQuantityDt) {
|
||||||
|
BaseQuantityDt param = (BaseQuantityDt) theParam;
|
||||||
|
String systemValue = param.getSystemElement().getValueAsString();
|
||||||
|
String unitsValue = param.getUnitsElement().getValueAsString();
|
||||||
|
ParamPrefixEnum cmpValue = ParamPrefixEnum.forValue(param.getComparatorElement().getValueAsString());
|
||||||
|
BigDecimal valueValue = param.getValueElement().getValue();
|
||||||
|
return new QuantityParam()
|
||||||
|
.setSystem(systemValue)
|
||||||
|
.setUnits(unitsValue)
|
||||||
|
.setPrefix(cmpValue)
|
||||||
|
.setValue(valueValue);
|
||||||
|
} else if (theParam instanceof QuantityParam) {
|
||||||
|
return (QuantityParam) theParam;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Invalid quantity type: " + theParam.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: change
|
||||||
|
issue: 2290
|
||||||
|
title: "In the JPA server. the SQL datatype used to index quantities has been changed from `NUMBER(19,2)` to
|
||||||
|
`double precision` (or equivalents depending on platform). This improves the query support for ssearching on
|
||||||
|
very small quantities."
|
|
@ -2,18 +2,18 @@
|
||||||
- item:
|
- item:
|
||||||
type: "add"
|
type: "add"
|
||||||
title: "The version of a few dependencies have been bumped to the latest versions
|
title: "The version of a few dependencies have been bumped to the latest versions
|
||||||
(dependent HAPI modules listed in brackets):
|
(dependent HAPI modules listed in brackets):
|
||||||
<ul>
|
* SLF4j (All Modules): 1.7.28 -> 1.7.30
|
||||||
<li>SLF4j (All Modules): 1.7.28 -> 1.7.30</li>
|
* Jackson (All Modules): 2.11.2 -> 2.12.1
|
||||||
<li>Woodstox (XML FHIR Parser): 4.4.1 -> 6.2.3 (Note that the Maven groupId has changed from <code>org.codehaus.woodstox</code> to <code>com.fasterxml.woodstox</code> and the Maven artifactId has changed from <code>woodstox-core-asl</code> to <code>woodstox-core</code> for this library)</li>
|
* Woodstox (XML FHIR Parser): 4.4.1 -> 6.2.3 (Note that the Maven groupId has changed from `org.codehaus.woodstox` to `com.fasterxml.woodstox` and the Maven artifactId has changed from `woodstox-core-asl` to `woodstox-core` for this library)
|
||||||
<li>Spring (JPA): 5.2.3.RELEASE -> 5.2.9.RELEASE</li>
|
* Spring (JPA): 5.2.3.RELEASE -> 5.2.9.RELEASE
|
||||||
<li>Datasource-Proxy (JPA): 1.5.1 -> 1.7</li>
|
* Datasource-Proxy (JPA): 1.5.1 -> 1.7
|
||||||
<li>Jetty (JPA Starter): 9.4.30.v20200611 -> 9.4.35.v20201120</li>
|
* Jetty (JPA Starter): 9.4.30.v20200611 -> 9.4.35.v20201120
|
||||||
<li>Guava (JP): 29.0-jre -> 30.1-jre</li>
|
* Guava (JP): 29.0-jre -> 30.1-jre
|
||||||
<li>Hibernate ORM (JPA Server): 5.4.22.FINAL -> 5.4.26.FINAL</li>
|
* Hibernate ORM (JPA Server): 5.4.22.FINAL -> 5.4.26.FINAL
|
||||||
<li>Spring (JPA Server): 5.2.9.RELEASE -> 5.3.2</li>
|
* Spring (JPA Server): 5.2.9.RELEASE -> 5.3.2
|
||||||
<li>Spring Data (JPA Server): 2.2.0.RELEASE -> 2.4.2</li>
|
* Spring Data (JPA Server): 2.2.0.RELEASE -> 2.4.2
|
||||||
<li>Hibernate Search (JPA Server): 5.11.5.FINAL -> 6.0.0.Final</li>
|
* Hibernate Search (JPA Server): 5.11.5.FINAL -> 6.0.0.Final
|
||||||
<li>Lucene(HAPI FHIR JPA Server): 5.5.5 -> 8.7.0</li>
|
* Lucene(HAPI FHIR JPA Server): 5.5.5 -> 8.7.0
|
||||||
<li>Spring Boot (JPA Starter): 2.2.6.RELEASE -> 2.4.1</li>
|
* Spring Boot (JPA Starter): 2.2.6.RELEASE -> 2.4.1
|
||||||
</ul>"
|
"
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||||
|
@ -27,7 +28,7 @@ import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
public interface IResourceIndexedSearchParamQuantityNormalizedDao extends JpaRepository<ResourceIndexedSearchParamQuantity, Long> {
|
public interface IResourceIndexedSearchParamQuantityNormalizedDao extends JpaRepository<ResourceIndexedSearchParamQuantityNormalized, Long> {
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("delete from ResourceIndexedSearchParamQuantityNormalized t WHERE t.myResourcePid = :resid")
|
@Query("delete from ResourceIndexedSearchParamQuantityNormalized t WHERE t.myResourcePid = :resid")
|
||||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||||
|
|
|
@ -31,7 +31,9 @@ import ca.uhn.fhir.jpa.dao.predicate.PredicateBuilderToken;
|
||||||
import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser;
|
import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||||
|
@ -43,12 +45,12 @@ import ca.uhn.fhir.jpa.search.builder.predicate.ResourceIdPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceLinkPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceLinkPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.SearchParamPresentPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.SearchParamPresentPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.SourcePredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.SourcePredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.StringPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.StringPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.TagPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.TagPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.TokenPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.TokenPredicateBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.predicate.UriPredicateBuilder;
|
import ca.uhn.fhir.jpa.search.builder.predicate.UriPredicateBuilder;
|
||||||
|
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
|
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
|
@ -185,14 +187,9 @@ public class QueryStack {
|
||||||
|
|
||||||
public void addSortOnQuantity(String theResourceName, String theParamName, boolean theAscending) {
|
public void addSortOnQuantity(String theResourceName, String theParamName, boolean theAscending) {
|
||||||
BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||||
|
|
||||||
QuantityBasePredicateBuilder sortPredicateBuilder = null;
|
|
||||||
if (myModelConfig.isNormalizedQuantitySearchSupported()) {
|
|
||||||
sortPredicateBuilder = mySqlBuilder.addQuantityNormalizedPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
|
||||||
} else {
|
|
||||||
sortPredicateBuilder = mySqlBuilder.addQuantityPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
|
||||||
|
|
||||||
}
|
QuantityBasePredicateBuilder sortPredicateBuilder;
|
||||||
|
sortPredicateBuilder = mySqlBuilder.addQuantityPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||||
|
|
||||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
|
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate(theResourceName, theParamName);
|
||||||
mySqlBuilder.addPredicate(hashIdentityPredicate);
|
mySqlBuilder.addPredicate(hashIdentityPredicate);
|
||||||
|
@ -272,33 +269,33 @@ public class QueryStack {
|
||||||
return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
|
return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {
|
private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
||||||
Condition orCondidtion = null;
|
Condition orCondidtion = null;
|
||||||
for (IQueryParameterType next : theNextAnd) {
|
for (IQueryParameterType next : theNextAnd) {
|
||||||
|
|
||||||
if (!(next instanceof CompositeParam<?, ?>)) {
|
if (!(next instanceof CompositeParam<?, ?>)) {
|
||||||
throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + next.getClass());
|
throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + next.getClass());
|
||||||
}
|
}
|
||||||
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next;
|
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next;
|
||||||
|
|
||||||
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
|
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
|
||||||
IQueryParameterType leftValue = cp.getLeftValue();
|
IQueryParameterType leftValue = cp.getLeftValue();
|
||||||
Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, left, leftValue, theRequestPartitionId);
|
Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, left, leftValue, theRequestPartitionId);
|
||||||
|
|
||||||
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
|
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
|
||||||
IQueryParameterType rightValue = cp.getRightValue();
|
IQueryParameterType rightValue = cp.getRightValue();
|
||||||
Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, right, rightValue, theRequestPartitionId);
|
Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, right, rightValue, theRequestPartitionId);
|
||||||
|
|
||||||
Condition andCondition = toAndPredicate(leftPredicate, rightPredicate);
|
Condition andCondition = toAndPredicate(leftPredicate, rightPredicate);
|
||||||
|
|
||||||
if (orCondidtion == null) {
|
if (orCondidtion == null) {
|
||||||
orCondidtion = toOrPredicate(andCondition);
|
orCondidtion = toOrPredicate(andCondition);
|
||||||
} else {
|
} else {
|
||||||
orCondidtion = toOrPredicate(orCondidtion, andCondition);
|
orCondidtion = toOrPredicate(orCondidtion, andCondition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return orCondidtion;
|
return orCondidtion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,11 +411,11 @@ public class QueryStack {
|
||||||
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
|
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
|
||||||
return theQueryStack3.createPredicateResourceId(null, Collections.singletonList(Collections.singletonList(param)), theResourceName, theFilter.getOperation(), theRequestPartitionId);
|
return theQueryStack3.createPredicateResourceId(null, Collections.singletonList(Collections.singletonList(param)), theResourceName, theFilter.getOperation(), theRequestPartitionId);
|
||||||
} else if (paramName.equals(IAnyResource.SP_RES_LANGUAGE)) {
|
} else if (paramName.equals(IAnyResource.SP_RES_LANGUAGE)) {
|
||||||
return theQueryStack3.createPredicateLanguage(Collections.singletonList(Collections.singletonList(new StringParam(theFilter.getValue()))), theFilter.getOperation());
|
return theQueryStack3.createPredicateLanguage(Collections.singletonList(Collections.singletonList(new StringParam(theFilter.getValue()))), theFilter.getOperation());
|
||||||
} else if (paramName.equals(Constants.PARAM_SOURCE)) {
|
} else if (paramName.equals(Constants.PARAM_SOURCE)) {
|
||||||
TokenParam param = new TokenParam();
|
TokenParam param = new TokenParam();
|
||||||
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
|
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
|
||||||
return createPredicateSource(null, Collections.singletonList(param));
|
return createPredicateSource(null, Collections.singletonList(param));
|
||||||
} else {
|
} else {
|
||||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
|
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
|
||||||
if (searchParam == null) {
|
if (searchParam == null) {
|
||||||
|
@ -642,20 +639,38 @@ public class QueryStack {
|
||||||
List<? extends IQueryParameterType> theList,
|
List<? extends IQueryParameterType> theList,
|
||||||
SearchFilterParser.CompareOperation theOperation,
|
SearchFilterParser.CompareOperation theOperation,
|
||||||
RequestPartitionId theRequestPartitionId) {
|
RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
||||||
QuantityBasePredicateBuilder join = null;
|
|
||||||
|
|
||||||
if (myModelConfig.isNormalizedQuantitySearchSupported()) {
|
|
||||||
join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityNormalizedPredicateBuilder(theSourceJoinColumn)).getResult();
|
|
||||||
} else {
|
|
||||||
join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityPredicateBuilder(theSourceJoinColumn)).getResult();
|
|
||||||
}
|
|
||||||
if (theList.get(0).getMissing() != null) {
|
if (theList.get(0).getMissing() != null) {
|
||||||
|
QuantityBasePredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityPredicateBuilder(theSourceJoinColumn)).getResult();
|
||||||
return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
|
return join.createPredicateParamMissingForNonReference(theResourceName, theSearchParam.getName(), theList.get(0).getMissing(), theRequestPartitionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<QuantityParam> quantityParams = theList
|
||||||
|
.stream()
|
||||||
|
.map(t -> QuantityParam.toQuantityParam(t))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
QuantityBasePredicateBuilder join = null;
|
||||||
|
boolean normalizedSearchEnabled = myModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
if (normalizedSearchEnabled) {
|
||||||
|
List<QuantityParam> normalizedQuantityParams = quantityParams
|
||||||
|
.stream()
|
||||||
|
.map(t -> UcumServiceUtil.toCanonicalQuantityOrNull(t))
|
||||||
|
.filter(t -> t != null)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (normalizedQuantityParams.size() == quantityParams.size()) {
|
||||||
|
join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityNormalizedPredicateBuilder(theSourceJoinColumn)).getResult();
|
||||||
|
quantityParams = normalizedQuantityParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (join == null) {
|
||||||
|
join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.QUANTITY, theSourceJoinColumn, theSearchParam.getName(), () -> mySqlBuilder.addQuantityPredicateBuilder(theSourceJoinColumn)).getResult();
|
||||||
|
}
|
||||||
|
|
||||||
List<Condition> codePredicates = new ArrayList<>();
|
List<Condition> codePredicates = new ArrayList<>();
|
||||||
for (IQueryParameterType nextOr : theList) {
|
for (QuantityParam nextOr : quantityParams) {
|
||||||
Condition singleCode = join.createPredicateQuantity(nextOr, theResourceName, theSearchParam.getName(), null, join, theOperation, theRequestPartitionId);
|
Condition singleCode = join.createPredicateQuantity(nextOr, theResourceName, theSearchParam.getName(), null, join, theOperation, theRequestPartitionId);
|
||||||
codePredicates.add(singleCode);
|
codePredicates.add(singleCode);
|
||||||
}
|
}
|
||||||
|
@ -923,7 +938,7 @@ public class QueryStack {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Condition searchForIdsWithAndOr(@Nullable DbColumn theSourceJoinColumn, String theResourceName, String theParamName, List<List<IQueryParameterType>> theAndOrParams, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
|
public Condition searchForIdsWithAndOr(@Nullable DbColumn theSourceJoinColumn, String theResourceName, String theParamName, List<List<IQueryParameterType>> theAndOrParams, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
||||||
if (theAndOrParams.isEmpty()) {
|
if (theAndOrParams.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1054,7 +1069,7 @@ public class QueryStack {
|
||||||
return toAndPredicate(andPredicates);
|
return toAndPredicate(andPredicates);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPredicateCompositeUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
public void addPredicateCompositeUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
|
@ -20,27 +20,10 @@ package ca.uhn.fhir.jpa.search.builder.predicate;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
|
|
||||||
import org.fhir.ucum.Pair;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
|
||||||
import com.healthmarketscience.sqlbuilder.ComboCondition;
|
|
||||||
import com.healthmarketscience.sqlbuilder.Condition;
|
|
||||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
|
||||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||||
import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser;
|
import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser;
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamBaseQuantity;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamBaseQuantity;
|
||||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||||
|
@ -48,7 +31,18 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
|
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
|
||||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
||||||
|
import com.healthmarketscience.sqlbuilder.ComboCondition;
|
||||||
|
import com.healthmarketscience.sqlbuilder.Condition;
|
||||||
|
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||||
|
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
|
||||||
public abstract class QuantityBasePredicateBuilder extends BaseSearchParamPredicateBuilder {
|
public abstract class QuantityBasePredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||||
|
@ -59,11 +53,7 @@ public abstract class QuantityBasePredicateBuilder extends BaseSearchParamPredic
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FhirContext myFhirContext;
|
private FhirContext myFhirContext;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ModelConfig myModelConfig;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -71,38 +61,13 @@ public abstract class QuantityBasePredicateBuilder extends BaseSearchParamPredic
|
||||||
super(theSearchSqlBuilder, theTable);
|
super(theSearchSqlBuilder, theTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Condition createPredicateQuantity(IQueryParameterType theParam, String theResourceName, String theParamName, CriteriaBuilder theBuilder, QuantityBasePredicateBuilder theFrom, SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
|
public Condition createPredicateQuantity(QuantityParam theParam, String theResourceName, String theParamName, CriteriaBuilder theBuilder, QuantityBasePredicateBuilder theFrom, SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
||||||
String systemValue;
|
|
||||||
String unitsValue;
|
|
||||||
ParamPrefixEnum cmpValue;
|
|
||||||
BigDecimal valueValue;
|
|
||||||
|
|
||||||
if (theParam instanceof BaseQuantityDt) {
|
String systemValue = theParam.getSystem();
|
||||||
BaseQuantityDt param = (BaseQuantityDt) theParam;
|
String unitsValue = theParam.getUnits();
|
||||||
systemValue = param.getSystemElement().getValueAsString();
|
ParamPrefixEnum cmpValue = theParam.getPrefix();
|
||||||
unitsValue = param.getUnitsElement().getValueAsString();
|
BigDecimal valueValue = theParam.getValue();
|
||||||
cmpValue = ParamPrefixEnum.forValue(param.getComparatorElement().getValueAsString());
|
|
||||||
valueValue = param.getValueElement().getValue();
|
|
||||||
} else if (theParam instanceof QuantityParam) {
|
|
||||||
QuantityParam param = (QuantityParam) theParam;
|
|
||||||
systemValue = param.getSystem();
|
|
||||||
unitsValue = param.getUnits();
|
|
||||||
cmpValue = param.getPrefix();
|
|
||||||
valueValue = param.getValue();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Invalid quantity type: " + theParam.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myModelConfig.isNormalizedQuantitySearchSupported()) {
|
|
||||||
//-- convert the value/unit to the canonical form if any to use by the search
|
|
||||||
Pair canonicalForm = UcumServiceUtil.getCanonicalForm(systemValue, valueValue, unitsValue);
|
|
||||||
if (canonicalForm != null) {
|
|
||||||
valueValue = new BigDecimal(canonicalForm.getValue().asDecimal());
|
|
||||||
unitsValue = canonicalForm.getCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Condition hashPredicate;
|
Condition hashPredicate;
|
||||||
if (!isBlank(systemValue) && !isBlank(unitsValue)) {
|
if (!isBlank(systemValue) && !isBlank(unitsValue)) {
|
||||||
long hash = ResourceIndexedSearchParamBaseQuantity.calculateHashSystemAndUnits(getPartitionSettings(), theRequestPartitionId, theResourceName, theParamName, systemValue, unitsValue);
|
long hash = ResourceIndexedSearchParamBaseQuantity.calculateHashSystemAndUnits(getPartitionSettings(), theRequestPartitionId, theResourceName, theParamName, systemValue, unitsValue);
|
||||||
|
@ -127,5 +92,6 @@ public abstract class QuantityBasePredicateBuilder extends BaseSearchParamPredic
|
||||||
|
|
||||||
public DbColumn getColumnValue() {
|
public DbColumn getColumnValue() {
|
||||||
return myColumnValue;
|
return myColumnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import static org.hamcrest.Matchers.empty;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||||
import static org.hamcrest.Matchers.matchesPattern;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
import java.io.IOException;
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import java.math.BigDecimal;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import java.util.Date;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
import java.util.List;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -33,15 +32,20 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import java.math.BigDecimal;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import java.util.Date;
|
||||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
import java.util.List;
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
import java.util.stream.Collectors;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.matchesPattern;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4CreateTest.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4CreateTest.class);
|
||||||
|
@ -51,7 +55,7 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
||||||
myDaoConfig.setResourceClientIdStrategy(new DaoConfig().getResourceClientIdStrategy());
|
myDaoConfig.setResourceClientIdStrategy(new DaoConfig().getResourceClientIdStrategy());
|
||||||
myDaoConfig.setDefaultSearchParamsCanBeOverridden(new DaoConfig().isDefaultSearchParamsCanBeOverridden());
|
myDaoConfig.setDefaultSearchParamsCanBeOverridden(new DaoConfig().isDefaultSearchParamsCanBeOverridden());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -337,9 +341,9 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithNormalizedQuantitySearchSupported() {
|
public void testCreateWithNormalizedQuantitySearchSupported_AlreadyCanonicalUnit() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.setStatus(Observation.ObservationStatus.FINAL);
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
Quantity q = new Quantity();
|
Quantity q = new Quantity();
|
||||||
|
@ -348,34 +352,38 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
q.setSystem("http://unitsofmeasure.org");
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
q.setCode("cm");
|
q.setCode("cm");
|
||||||
obs.setValue(q);
|
obs.setValue(q);
|
||||||
|
|
||||||
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
assertTrue(myObservationDao.create(obs).getCreated());
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
// Same value should be placed in both quantity tables
|
||||||
map.setLoadSynchronous(true);
|
runInTransaction(()->{
|
||||||
QuantityParam qp = new QuantityParam();
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
qp.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL);
|
assertEquals(1, quantityIndexes.size());
|
||||||
qp.setValue(new BigDecimal("0.012"));
|
assertEquals("1.2", Double.toString(quantityIndexes.get(0).getValue().doubleValue()));
|
||||||
qp.setUnits("m");
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("cm", quantityIndexes.get(0).getUnits());
|
||||||
map.add(Observation.SP_VALUE_QUANTITY, qp);
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
IBundleProvider found = myObservationDao.search(map);
|
assertEquals(1, normalizedQuantityIndexes.size());
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(found);
|
assertEquals("0.012", Double.toString(normalizedQuantityIndexes.get(0).getValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", normalizedQuantityIndexes.get(0).getSystem());
|
||||||
List<IBaseResource> resources = found.getResources(0, found.size());
|
assertEquals("m", normalizedQuantityIndexes.get(0).getUnits());
|
||||||
|
});
|
||||||
assertEquals(1, ids.size());
|
|
||||||
|
SearchParameterMap map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
ourLog.info("Observation2: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resources.get(0)));
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.012"))
|
||||||
|
.setUnits("m")
|
||||||
|
);
|
||||||
|
assertEquals(1, toUnqualifiedVersionlessIdValues(myObservationDao.search(map)).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithNormalizedQuantitySearchSupportedWithVerySmallNumber() {
|
public void testCreateWithNormalizedQuantitySearchSupported_SmallerThanCanonicalUnit() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.setStatus(Observation.ObservationStatus.FINAL);
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
Quantity q = new Quantity();
|
Quantity q = new Quantity();
|
||||||
|
@ -384,102 +392,358 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
q.setSystem("http://unitsofmeasure.org");
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
q.setCode("mm");
|
q.setCode("mm");
|
||||||
obs.setValue(q);
|
obs.setValue(q);
|
||||||
|
|
||||||
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
assertTrue(myObservationDao.create(obs).getCreated());
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
myCaptureQueriesListener.logInsertQueries();
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
|
||||||
map.setLoadSynchronous(true);
|
// Original value should be in Quantity index, normalized should be in normalized table
|
||||||
QuantityParam qp = new QuantityParam();
|
runInTransaction(()->{
|
||||||
qp.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL);
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
qp.setValue(new BigDecimal("0.0000000012"));
|
assertEquals(1, quantityIndexes.size());
|
||||||
qp.setUnits("m");
|
double d = quantityIndexes.get(0).getValue().doubleValue();
|
||||||
|
assertEquals("1.2E-6", Double.toString(d));
|
||||||
map.add(Observation.SP_VALUE_QUANTITY, qp);
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("mm", quantityIndexes.get(0).getUnits());
|
||||||
IBundleProvider found = myObservationDao.search(map);
|
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(found);
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, normalizedQuantityIndexes.size());
|
||||||
List<IBaseResource> resources = found.getResources(0, found.size());
|
assertEquals("1.2E-9", Double.toString(normalizedQuantityIndexes.get(0).getValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", normalizedQuantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("m", normalizedQuantityIndexes.get(0).getUnits());
|
||||||
|
});
|
||||||
|
|
||||||
|
String searchSql;
|
||||||
|
SearchParameterMap map;
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Try with normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000000012"))
|
||||||
|
.setUnits("m")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY_NRML t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '1.2E-9'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
// Try with non-normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
.setUnits("mm")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY_NRML t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '1.2E-9'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
// Try with no units value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '0.0000012'"));
|
||||||
assertEquals(1, ids.size());
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
ourLog.info("Observation2: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resources.get(0)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithNormalizedQuantitySearchSupportedWithVerySmallNumber2() {
|
public void testCreateWithNormalizedQuantitySearchSupported_SmallerThanCanonicalUnit2() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.setStatus(Observation.ObservationStatus.FINAL);
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
Quantity q = new Quantity();
|
Quantity q = new Quantity();
|
||||||
q.setValueElement(new DecimalType(149597.870691));
|
q.setValueElement(new DecimalType("149597.870691"));
|
||||||
q.setUnit("MM");
|
q.setUnit("MM");
|
||||||
q.setSystem("http://unitsofmeasure.org");
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
q.setCode("mm");
|
q.setCode("mm");
|
||||||
obs.setValue(q);
|
obs.setValue(q);
|
||||||
|
|
||||||
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
assertTrue(myObservationDao.create(obs).getCreated());
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
|
||||||
|
// Original value should be in Quantity index, normalized should be in normalized table
|
||||||
|
runInTransaction(()->{
|
||||||
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, quantityIndexes.size());
|
||||||
|
assertEquals("149597.870691", Double.toString(quantityIndexes.get(0).getValue().doubleValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("mm", quantityIndexes.get(0).getUnits());
|
||||||
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, normalizedQuantityIndexes.size());
|
||||||
|
assertEquals("149.597870691", Double.toString(normalizedQuantityIndexes.get(0).getValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", normalizedQuantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("m", normalizedQuantityIndexes.get(0).getUnits());
|
||||||
|
});
|
||||||
|
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
map.setLoadSynchronous(true);
|
map.setLoadSynchronous(true);
|
||||||
QuantityParam qp = new QuantityParam();
|
QuantityParam qp = new QuantityParam();
|
||||||
qp.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL);
|
qp.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL);
|
||||||
qp.setValue(new BigDecimal("149.597870691"));
|
qp.setValue(new BigDecimal("149.597870691"));
|
||||||
qp.setUnits("m");
|
qp.setUnits("m");
|
||||||
|
|
||||||
map.add(Observation.SP_VALUE_QUANTITY, qp);
|
map.add(Observation.SP_VALUE_QUANTITY, qp);
|
||||||
|
|
||||||
IBundleProvider found = myObservationDao.search(map);
|
IBundleProvider found = myObservationDao.search(map);
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(found);
|
List<String> ids = toUnqualifiedVersionlessIdValues(found);
|
||||||
|
|
||||||
List<IBaseResource> resources = found.getResources(0, found.size());
|
List<IBaseResource> resources = found.getResources(0, found.sizeOrThrowNpe());
|
||||||
|
|
||||||
assertEquals(1, ids.size());
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
ourLog.info("Observation2: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resources.get(0)));
|
ourLog.info("Observation2: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resources.get(0)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithNormalizedQuantitySearchSupportedWithLargeNumber() {
|
public void testCreateWithNormalizedQuantitySearchSupported_LargerThanCanonicalUnit() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
|
Quantity q = new Quantity();
|
||||||
|
q.setValueElement(new DecimalType("95.7412345"));
|
||||||
|
q.setUnit("kg/dL");
|
||||||
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
|
q.setCode("kg/dL");
|
||||||
|
obs.setValue(q);
|
||||||
|
|
||||||
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
|
||||||
|
// Original value should be in Quantity index, normalized should be in normalized table
|
||||||
|
runInTransaction(()->{
|
||||||
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, quantityIndexes.size());
|
||||||
|
assertEquals("95.7412345", Double.toString(quantityIndexes.get(0).getValue().doubleValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("kg/dL", quantityIndexes.get(0).getUnits());
|
||||||
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, normalizedQuantityIndexes.size());
|
||||||
|
assertEquals("9.57412345E8", Double.toString(normalizedQuantityIndexes.get(0).getValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", normalizedQuantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("g.m-3", normalizedQuantityIndexes.get(0).getUnits());
|
||||||
|
});
|
||||||
|
|
||||||
|
SearchParameterMap map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("957412345"))
|
||||||
|
.setUnits("g.m-3")
|
||||||
|
);
|
||||||
|
assertEquals(1, toUnqualifiedVersionlessIdValues(myObservationDao.search(map)).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithNormalizedQuantitySearchSupported_NonCanonicalUnit() {
|
||||||
|
|
||||||
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.setStatus(Observation.ObservationStatus.FINAL);
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
Quantity q = new Quantity();
|
Quantity q = new Quantity();
|
||||||
q.setValueElement(new DecimalType(95.7412345));
|
q.setValueElement(new DecimalType(95.7412345));
|
||||||
q.setUnit("kg/dL");
|
q.setUnit("kg/dL");
|
||||||
q.setSystem("http://unitsofmeasure.org");
|
q.setSystem("http://example.com");
|
||||||
q.setCode("kg/dL");
|
q.setCode("kg/dL");
|
||||||
obs.setValue(q);
|
obs.setValue(q);
|
||||||
|
|
||||||
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
assertTrue(myObservationDao.create(obs).getCreated());
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
// Original value should be in Quantity index, normalized should be in normalized table
|
||||||
map.setLoadSynchronous(true);
|
runInTransaction(() -> {
|
||||||
QuantityParam qp = new QuantityParam();
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t -> t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
qp.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL);
|
assertEquals(1, quantityIndexes.size());
|
||||||
qp.setValue(new BigDecimal("957412345"));
|
assertEquals("95.7412345", Double.toString(quantityIndexes.get(0).getValue().doubleValue()));
|
||||||
qp.setUnits("g.m-3");
|
assertEquals("http://example.com", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("kg/dL", quantityIndexes.get(0).getUnits());
|
||||||
map.add(Observation.SP_VALUE_QUANTITY, qp);
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t -> t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
IBundleProvider found = myObservationDao.search(map);
|
assertEquals(0, normalizedQuantityIndexes.size());
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(found);
|
});
|
||||||
|
|
||||||
List<IBaseResource> resources = found.getResources(0, found.size());
|
List<String> ids;
|
||||||
|
|
||||||
|
// Search should succeed using non-normalized table
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
SearchParameterMap map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem("http://example.com")
|
||||||
|
.setValue(95.7412345)
|
||||||
|
.setUnits("kg/dL")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '95.7412345'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithNormalizedQuantityStorageSupported_SmallerThanCanonicalUnit() {
|
||||||
|
|
||||||
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
|
Quantity q = new Quantity();
|
||||||
|
q.setValueElement(new DecimalType(0.0000012));
|
||||||
|
q.setUnit("MM");
|
||||||
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
|
q.setCode("mm");
|
||||||
|
obs.setValue(q);
|
||||||
|
|
||||||
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
myCaptureQueriesListener.logInsertQueries();
|
||||||
|
|
||||||
|
// Original value should be in Quantity index, normalized should be in normalized table
|
||||||
|
runInTransaction(()->{
|
||||||
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, quantityIndexes.size());
|
||||||
|
double d = quantityIndexes.get(0).getValue().doubleValue();
|
||||||
|
assertEquals("1.2E-6", Double.toString(d));
|
||||||
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("mm", quantityIndexes.get(0).getUnits());
|
||||||
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, normalizedQuantityIndexes.size());
|
||||||
|
assertEquals("1.2E-9", Double.toString(normalizedQuantityIndexes.get(0).getValue()));
|
||||||
|
assertEquals("http://unitsofmeasure.org", normalizedQuantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("m", normalizedQuantityIndexes.get(0).getUnits());
|
||||||
|
});
|
||||||
|
|
||||||
|
String searchSql;
|
||||||
|
SearchParameterMap map;
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Try with normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000000012"))
|
||||||
|
.setUnits("m")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '1.2E-9'"));
|
||||||
|
assertEquals(0, ids.size());
|
||||||
|
|
||||||
|
// Try with non-normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
.setUnits("mm")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '0.0000012'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
// Try with no units value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '0.0000012'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithNormalizedQuantitySearchNotSupported_SmallerThanCanonicalUnit() {
|
||||||
|
|
||||||
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setStatus(Observation.ObservationStatus.FINAL);
|
||||||
|
Quantity q = new Quantity();
|
||||||
|
q.setValueElement(new DecimalType(0.0000012));
|
||||||
|
q.setUnit("MM");
|
||||||
|
q.setSystem("http://unitsofmeasure.org");
|
||||||
|
q.setCode("mm");
|
||||||
|
obs.setValue(q);
|
||||||
|
|
||||||
|
ourLog.info("Observation1: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
assertTrue(myObservationDao.create(obs).getCreated());
|
||||||
|
myCaptureQueriesListener.logInsertQueries();
|
||||||
|
|
||||||
|
// Original value should be in Quantity index, no normalized should be in normalized table
|
||||||
|
runInTransaction(()->{
|
||||||
|
List<ResourceIndexedSearchParamQuantity> quantityIndexes = myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(1, quantityIndexes.size());
|
||||||
|
double d = quantityIndexes.get(0).getValue().doubleValue();
|
||||||
|
assertEquals("1.2E-6", Double.toString(d));
|
||||||
|
assertEquals("http://unitsofmeasure.org", quantityIndexes.get(0).getSystem());
|
||||||
|
assertEquals("mm", quantityIndexes.get(0).getUnits());
|
||||||
|
|
||||||
|
List<ResourceIndexedSearchParamQuantityNormalized> normalizedQuantityIndexes = myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t->t.getParamName().equals("value-quantity")).collect(Collectors.toList());
|
||||||
|
assertEquals(0, normalizedQuantityIndexes.size());
|
||||||
|
});
|
||||||
|
|
||||||
|
String searchSql;
|
||||||
|
SearchParameterMap map;
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Try with normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000000012"))
|
||||||
|
.setUnits("m")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '1.2E-9'"));
|
||||||
|
assertEquals(0, ids.size());
|
||||||
|
|
||||||
|
// Try with non-normalized value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL)
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
.setUnits("mm")
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '0.0000012'"));
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
// Try with no units value
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
map = SearchParameterMap.newSynchronous(Observation.SP_VALUE_QUANTITY, new QuantityParam()
|
||||||
|
.setValue(new BigDecimal("0.0000012"))
|
||||||
|
);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map));
|
||||||
|
searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true,true);
|
||||||
|
assertThat(searchSql, containsString("HFJ_SPIDX_QUANTITY t0"));
|
||||||
|
assertThat(searchSql, containsString("t0.SP_VALUE = '0.0000012'"));
|
||||||
assertEquals(1, ids.size());
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
ourLog.info("Observation2: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resources.get(0)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
@ -86,8 +87,8 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void after() {
|
public void after() {
|
||||||
myDaoConfig.setValidateSearchParameterExpressionsOnSave(new DaoConfig().isValidateSearchParameterExpressionsOnSave());
|
myDaoConfig.setValidateSearchParameterExpressionsOnSave(new DaoConfig().isValidateSearchParameterExpressionsOnSave());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeDisableResultReuse() {
|
public void beforeDisableResultReuse() {
|
||||||
|
@ -117,8 +118,8 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStoreSearchParamWithBracketsInExpressionNormalizedQuantitySearchSupported() {
|
public void testStoreSearchParamWithBracketsInExpressionNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
myDaoConfig.setMarkResourcesForReindexingUponSearchParameterChange(true);
|
myDaoConfig.setMarkResourcesForReindexingUponSearchParameterChange(true);
|
||||||
|
|
||||||
SearchParameter fooSp = new SearchParameter();
|
SearchParameter fooSp = new SearchParameter();
|
||||||
|
@ -138,8 +139,8 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStoreSearchParamWithBracketsInExpressionNormalizedQuantityStorageSupported() {
|
public void testStoreSearchParamWithBracketsInExpressionNormalizedQuantityStorageSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
myDaoConfig.setMarkResourcesForReindexingUponSearchParameterChange(true);
|
myDaoConfig.setMarkResourcesForReindexingUponSearchParameterChange(true);
|
||||||
|
|
||||||
SearchParameter fooSp = new SearchParameter();
|
SearchParameter fooSp = new SearchParameter();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.DateParam;
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
|
@ -10,7 +11,16 @@ import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.DateType;
|
||||||
|
import org.hl7.fhir.r4.model.DecimalType;
|
||||||
|
import org.hl7.fhir.r4.model.Location;
|
||||||
|
import org.hl7.fhir.r4.model.MedicationRequest;
|
||||||
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.Quantity;
|
||||||
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
|
import org.hl7.fhir.r4.model.Task;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -21,8 +31,12 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4SearchMissingTest.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4SearchMissingTest.class);
|
||||||
|
@ -31,10 +45,10 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
public void beforeResetMissing() {
|
public void beforeResetMissing() {
|
||||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED);
|
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void afterResetSearch() {
|
public void afterResetSearch() {
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,9 +94,9 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexMissingFieldsDisabledDontCreateIndexesWithNormalizedQuantitySearchSupported() {
|
public void testIndexMissingFieldsDisabledDontCreateIndexesWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.setActive(true);
|
org.setActive(true);
|
||||||
myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
|
myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
@ -94,12 +108,12 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
assertThat(myResourceIndexedSearchParamQuantityDao.findAll(), empty());
|
assertThat(myResourceIndexedSearchParamQuantityDao.findAll(), empty());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexMissingFieldsDisabledDontCreateIndexesWithNormalizedQuantityStorageSupported() {
|
public void testIndexMissingFieldsDisabledDontCreateIndexesWithNormalizedQuantityStorageSupported() {
|
||||||
|
|
||||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.setActive(true);
|
org.setActive(true);
|
||||||
myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
|
myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
@ -111,7 +125,7 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
assertThat(myResourceIndexedSearchParamQuantityDao.findAll(), empty());
|
assertThat(myResourceIndexedSearchParamQuantityDao.findAll(), empty());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Test
|
@Test
|
||||||
public void testSearchResourceReferenceMissingChain() {
|
public void testSearchResourceReferenceMissingChain() {
|
||||||
|
@ -221,8 +235,8 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
String locId = myLocationDao.create(new Location(), mySrd).getId().toUnqualifiedVersionless().getValue();
|
String locId = myLocationDao.create(new Location(), mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
String locId2 = myLocationDao.create(new Location().setPosition(new Location.LocationPositionComponent(new DecimalType(10), new DecimalType(10))), mySrd).getId().toUnqualifiedVersionless().getValue();
|
String locId2 = myLocationDao.create(new Location().setPosition(new Location.LocationPositionComponent(new DecimalType(10), new DecimalType(10))), mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
ourLog.info("Coords:\n * {}", myResourceIndexedSearchParamCoordsDao.findAll().stream().map(t->t.toString()).collect(Collectors.joining("\n * ")));
|
ourLog.info("Coords:\n * {}", myResourceIndexedSearchParamCoordsDao.findAll().stream().map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -309,8 +323,8 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMissingQuantityWithNormalizedQuantitySearchSupported() {
|
public void testSearchWithMissingQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
IIdType notMissing;
|
IIdType notMissing;
|
||||||
IIdType missing;
|
IIdType missing;
|
||||||
{
|
{
|
||||||
|
@ -324,6 +338,12 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
obs.setValue(new Quantity(123));
|
obs.setValue(new Quantity(123));
|
||||||
notMissing = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();
|
notMissing = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runInTransaction(() -> {
|
||||||
|
ourLog.info("Quantity Indexes:\n * {}", myResourceIndexedSearchParamQuantityDao.findAll().stream().filter(t -> t.getParamName().equals("value-quantity")).map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||||
|
ourLog.info("Normalized Quantity Indexes:\n * {}", myResourceIndexedSearchParamQuantityNormalizedDao.findAll().stream().filter(t -> t.getParamName().equals("value-quantity")).map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||||
|
});
|
||||||
|
|
||||||
// Quantity Param
|
// Quantity Param
|
||||||
{
|
{
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
@ -341,17 +361,19 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
QuantityParam param = new QuantityParam();
|
QuantityParam param = new QuantityParam();
|
||||||
param.setMissing(true);
|
param.setMissing(true);
|
||||||
params.add(Observation.SP_VALUE_QUANTITY, param);
|
params.add(Observation.SP_VALUE_QUANTITY, param);
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
List<IIdType> patients = toUnqualifiedVersionlessIds(myObservationDao.search(params));
|
List<IIdType> patients = toUnqualifiedVersionlessIds(myObservationDao.search(params));
|
||||||
|
myCaptureQueriesListener.logSelectQueries();
|
||||||
assertThat(patients, containsInRelativeOrder(missing));
|
assertThat(patients, containsInRelativeOrder(missing));
|
||||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMissingQuantityWithNormalizedQuantityStorageSupported() {
|
public void testSearchWithMissingQuantityWithNormalizedQuantityStorageSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
IIdType notMissing;
|
IIdType notMissing;
|
||||||
IIdType missing;
|
IIdType missing;
|
||||||
{
|
{
|
||||||
|
@ -386,10 +408,10 @@ public class FhirResourceDaoR4SearchMissingTest extends BaseJpaR4Test {
|
||||||
assertThat(patients, containsInRelativeOrder(missing));
|
assertThat(patients, containsInRelativeOrder(missing));
|
||||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMissingReference() {
|
public void testSearchWithMissingReference() {
|
||||||
IIdType orgId = myOrganizationDao.create(new Organization(), mySrd).getId().toUnqualifiedVersionless();
|
IIdType orgId = myOrganizationDao.create(new Organization(), mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
@ -185,8 +186,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
|
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
|
||||||
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
|
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
|
||||||
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeDisableCacheReuse() {
|
public void beforeDisableCacheReuse() {
|
||||||
|
@ -1236,8 +1237,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexNoDuplicatesQuantityWithNormalizedQuantitySearchSupported() {
|
public void testIndexNoDuplicatesQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Substance res = new Substance();
|
Substance res = new Substance();
|
||||||
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
||||||
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
||||||
|
@ -1246,20 +1247,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantity> type = ResourceIndexedSearchParamQuantity.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(2, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantityNormalized> type = ResourceIndexedSearchParamQuantityNormalized.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(2, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
||||||
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 12300, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm"))));
|
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 12300, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm"))));
|
||||||
assertThat(actual, contains(id));
|
assertThat(actual, contains(id));
|
||||||
|
@ -1268,26 +1255,12 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQuantityWithNormalizedQuantitySearchSupported_InvalidUCUMCode() {
|
public void testQuantityWithNormalizedQuantitySearchSupported_InvalidUCUMCode() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Substance res = new Substance();
|
Substance res = new Substance();
|
||||||
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("FOO").setValue(123);
|
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("FOO").setValue(123);
|
||||||
|
|
||||||
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantity> type = ResourceIndexedSearchParamQuantity.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantityNormalized> type = ResourceIndexedSearchParamQuantityNormalized.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
||||||
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, UcumServiceUtil.UCUM_CODESYSTEM_URL, "FOO"))));
|
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, UcumServiceUtil.UCUM_CODESYSTEM_URL, "FOO"))));
|
||||||
|
@ -1297,27 +1270,13 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQuantityWithNormalizedQuantitySearchSupported_NotUCUM() {
|
public void testQuantityWithNormalizedQuantitySearchSupported_NotUCUM() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Substance res = new Substance();
|
Substance res = new Substance();
|
||||||
res.addInstance().getQuantity().setSystem("http://bar").setCode("FOO").setValue(123);
|
res.addInstance().getQuantity().setSystem("http://bar").setCode("FOO").setValue(123);
|
||||||
|
|
||||||
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantity> type = ResourceIndexedSearchParamQuantity.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantityNormalized> type = ResourceIndexedSearchParamQuantityNormalized.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(1, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
||||||
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, "http://bar", "FOO"))));
|
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, "http://bar", "FOO"))));
|
||||||
assertThat(actual, contains(id));
|
assertThat(actual, contains(id));
|
||||||
|
@ -1326,8 +1285,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexNoDuplicatesQuantityWithNormalizedQuantityStorageSupported() {
|
public void testIndexNoDuplicatesQuantityWithNormalizedQuantityStorageSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
Substance res = new Substance();
|
Substance res = new Substance();
|
||||||
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
||||||
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
res.addInstance().getQuantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("m").setValue(123);
|
||||||
|
@ -1336,20 +1295,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
IIdType id = mySubstanceDao.create(res, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantity> type = ResourceIndexedSearchParamQuantity.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(2, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
runInTransaction(() -> {
|
|
||||||
Class<ResourceIndexedSearchParamQuantityNormalized> type = ResourceIndexedSearchParamQuantityNormalized.class;
|
|
||||||
List<?> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList();
|
|
||||||
ourLog.info(toStringMultiline(results));
|
|
||||||
assertEquals(2, results.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
List<IIdType> actual = toUnqualifiedVersionlessIds(
|
||||||
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, UcumServiceUtil.UCUM_CODESYSTEM_URL, "m"))));
|
mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, UcumServiceUtil.UCUM_CODESYSTEM_URL, "m"))));
|
||||||
assertThat(actual, contains(id));
|
assertThat(actual, contains(id));
|
||||||
|
@ -2753,8 +2698,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchByMoneyParamWithNormalizedQuantitySearchSupported() {
|
public void testSearchByMoneyParamWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
ChargeItem ci = new ChargeItem();
|
ChargeItem ci = new ChargeItem();
|
||||||
ci.getPriceOverride().setValue(123).setCurrency("$");
|
ci.getPriceOverride().setValue(123).setCurrency("$");
|
||||||
|
|
||||||
|
@ -3119,8 +3064,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchQuantityWithNormalizedQuantitySearchSupported() {
|
public void testSearchQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Condition c1 = new Condition();
|
Condition c1 = new Condition();
|
||||||
c1.setAbatement(new Range().setLow(new SimpleQuantity().setValue(1L)).setHigh(new SimpleQuantity().setValue(1L)));
|
c1.setAbatement(new Range().setLow(new SimpleQuantity().setValue(1L)).setHigh(new SimpleQuantity().setValue(1L)));
|
||||||
String id1 = myConditionDao.create(c1).getId().toUnqualifiedVersionless().getValue();
|
String id1 = myConditionDao.create(c1).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||||
|
@ -143,8 +144,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
|
||||||
myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum());
|
myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum());
|
||||||
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
|
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
|
||||||
myDaoConfig.setDisableHashBasedSearches(false);
|
myDaoConfig.setDisableHashBasedSearches(false);
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeInitialize() {
|
public void beforeInitialize() {
|
||||||
|
@ -1193,8 +1194,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComponentQuantityWithNormalizedQuantitySearchSupported() {
|
public void testComponentQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm")))
|
||||||
|
@ -1216,8 +1217,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComponentQuantityWithNormalizedQuantityStorageSupported() {
|
public void testComponentQuantityWithNormalizedQuantityStorageSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm")))
|
||||||
|
@ -1292,8 +1293,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCompositeParamQuantityWithNormalizedQuantitySearchSupported() {
|
public void testSearchCompositeParamQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
|
@ -161,8 +162,8 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
|
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
|
||||||
myDaoConfig.setEnforceReferenceTargetTypes(new DaoConfig().isEnforceReferenceTargetTypes());
|
myDaoConfig.setEnforceReferenceTargetTypes(new DaoConfig().isEnforceReferenceTargetTypes());
|
||||||
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
|
@ -581,8 +582,8 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChoiceParamQuantityWithNormalizedQuantitySearchSupported() {
|
public void testChoiceParamQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation o3 = new Observation();
|
Observation o3 = new Observation();
|
||||||
o3.getCode().addCoding().setSystem("foo").setCode("testChoiceParam03");
|
o3.getCode().addCoding().setSystem("foo").setCode("testChoiceParam03");
|
||||||
o3.setValue(new Quantity(QuantityComparator.GREATER_THAN, 123.0, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm", "cm")); // 0.0123m
|
o3.setValue(new Quantity(QuantityComparator.GREATER_THAN, 123.0, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm", "cm")); // 0.0123m
|
||||||
|
@ -682,8 +683,8 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChoiceParamQuantityPrecisionWithNormalizedQuantitySearchSupported() {
|
public void testChoiceParamQuantityPrecisionWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation o3 = new Observation();
|
Observation o3 = new Observation();
|
||||||
o3.getCode().addCoding().setSystem("foo").setCode("testChoiceParam03");
|
o3.getCode().addCoding().setSystem("foo").setCode("testChoiceParam03");
|
||||||
o3.setValue(new Quantity(null, 123.01, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm", "cm")); // 0.012301 m
|
o3.setValue(new Quantity(null, 123.01, UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm", "cm")); // 0.012301 m
|
||||||
|
@ -3500,9 +3501,10 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSortByQuantityWithNormalizedQuantitySearchSupported() {
|
@Disabled
|
||||||
|
public void testSortByQuantityWithNormalizedQuantitySearchFullSupported() {
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
|
||||||
|
// myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_FULL_SUPPORTED);
|
||||||
Observation res;
|
Observation res;
|
||||||
|
|
||||||
res = new Observation();
|
res = new Observation();
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
|
@ -23,7 +24,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
|
@ -61,7 +61,6 @@ import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.hl7.fhir.r4.model.Resource;
|
import org.hl7.fhir.r4.model.Resource;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
@ -110,8 +109,8 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
public void after() {
|
public void after() {
|
||||||
myDaoConfig.setAllowInlineMatchUrlReferences(false);
|
myDaoConfig.setAllowInlineMatchUrlReferences(false);
|
||||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeDisableResultReuse() {
|
public void beforeDisableResultReuse() {
|
||||||
|
@ -3131,7 +3130,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithConditionalUpdateDoesntUpdateIfNoChangeWithNormalizedQuantitySearchSupported() {
|
public void testTransactionWithConditionalUpdateDoesntUpdateIfNoChangeWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.addIdentifier()
|
obs.addIdentifier()
|
||||||
.setSystem("http://acme.org")
|
.setSystem("http://acme.org")
|
||||||
|
|
|
@ -1,20 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import static java.util.Comparator.comparing;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import java.math.BigDecimal;
|
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
||||||
import java.util.ArrayList;
|
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
||||||
import java.util.Collection;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import java.util.HashMap;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
import java.util.HashSet;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
import java.util.List;
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import java.util.Map;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||||
import java.util.Set;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||||
import java.util.stream.Collectors;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||||
import org.hl7.fhir.dstu2.model.SimpleQuantity;
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache;
|
||||||
|
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||||
|
import ca.uhn.fhir.util.HapiExtensions;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.hl7.fhir.r4.model.BooleanType;
|
import org.hl7.fhir.r4.model.BooleanType;
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
|
@ -24,47 +33,30 @@ import org.hl7.fhir.r4.model.Extension;
|
||||||
import org.hl7.fhir.r4.model.Observation;
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.r4.model.Quantity;
|
import org.hl7.fhir.r4.model.Quantity;
|
||||||
import org.hl7.fhir.r4.model.Range;
|
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.hl7.fhir.r4.model.SearchParameter;
|
import org.hl7.fhir.r4.model.SearchParameter;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import static java.util.Comparator.comparing;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
|
||||||
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache;
|
|
||||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
|
||||||
import ca.uhn.fhir.util.HapiExtensions;
|
|
||||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
|
||||||
|
|
||||||
public class SearchParamExtractorR4Test {
|
public class SearchParamExtractorR4Test {
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorR4Test.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorR4Test.class);
|
||||||
private static FhirContext ourCtx = FhirContext.forCached(FhirVersionEnum.R4);
|
private static FhirContext ourCtx = FhirContext.forCached(FhirVersionEnum.R4);
|
||||||
private static IValidationSupport ourValidationSupport;
|
|
||||||
private MySearchParamRegistry mySearchParamRegistry;
|
private MySearchParamRegistry mySearchParamRegistry;
|
||||||
private PartitionSettings myPartitionSettings;
|
private PartitionSettings myPartitionSettings;
|
||||||
|
|
||||||
|
@ -81,7 +73,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.addCategory().addCoding().setSystem("SYSTEM").setCode("CODE");
|
obs.addCategory().addCoding().setSystem("SYSTEM").setCode("CODE");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs);
|
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs);
|
||||||
assertEquals(1, tokens.size());
|
assertEquals(1, tokens.size());
|
||||||
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
||||||
|
@ -95,7 +87,7 @@ public class SearchParamExtractorR4Test {
|
||||||
SearchParameter sp = new SearchParameter();
|
SearchParameter sp = new SearchParameter();
|
||||||
sp.addUseContext().setCode(new Coding().setSystem("http://system").setCode("code"));
|
sp.addUseContext().setCode(new Coding().setSystem("http://system").setCode("code"));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(sp);
|
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(sp);
|
||||||
assertEquals(1, tokens.size());
|
assertEquals(1, tokens.size());
|
||||||
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
||||||
|
@ -109,7 +101,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -138,7 +130,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -162,7 +154,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -191,7 +183,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
obs.getCode().addCoding().setSystem("http://system").setCode("code").setDisplay("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -216,7 +208,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.addIdentifier().setSystem("sys").setValue("val").getType().setText("Help Im a Bug");
|
obs.addIdentifier().setSystem("sys").setValue("val").getType().setText("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -246,7 +238,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.addIdentifier().setSystem("sys").setValue("val").getType().setText("Help Im a Bug");
|
obs.addIdentifier().setSystem("sys").setValue("val").getType().setText("Help Im a Bug");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), myPartitionSettings, ourCtx, mySearchParamRegistry);
|
||||||
|
|
||||||
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
List<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -267,7 +259,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Encounter enc = new Encounter();
|
Encounter enc = new Encounter();
|
||||||
enc.addLocation().setLocation(new Reference("Location/123"));
|
enc.addLocation().setLocation(new Reference("Location/123"));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location");
|
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location");
|
||||||
assertNotNull(param);
|
assertNotNull(param);
|
||||||
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(enc);
|
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(enc);
|
||||||
|
@ -282,7 +274,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Consent consent = new Consent();
|
Consent consent = new Consent();
|
||||||
consent.setSource(new Reference().setReference("Consent/999"));
|
consent.setSource(new Reference().setReference("Consent/999"));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE);
|
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE);
|
||||||
assertNotNull(param);
|
assertNotNull(param);
|
||||||
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(consent);
|
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(consent);
|
||||||
|
@ -297,7 +289,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addIdentifier().setSystem("sys").setValue("val");
|
p.addIdentifier().setSystem("sys").setValue("val");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Patient", Patient.SP_IDENTIFIER);
|
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Patient", Patient.SP_IDENTIFIER);
|
||||||
assertNotNull(param);
|
assertNotNull(param);
|
||||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> params = extractor.extractSearchParamTokens(p, param);
|
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> params = extractor.extractSearchParamTokens(p, param);
|
||||||
|
@ -319,7 +311,7 @@ public class SearchParamExtractorR4Test {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addExtension("http://patext", new Reference("Organization/AAA"));
|
patient.addExtension("http://patext", new Reference("Organization/AAA"));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(patient);
|
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(patient);
|
||||||
assertEquals(1, links.size());
|
assertEquals(1, links.size());
|
||||||
|
|
||||||
|
@ -335,7 +327,7 @@ public class SearchParamExtractorR4Test {
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code2")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code2")))
|
||||||
.setValue(new Quantity().setSystem("http://bar").setCode("code2").setValue(200));
|
.setValue(new Quantity().setSystem("http://bar").setCode("code2").setValue(200));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
Set<ResourceIndexedSearchParamQuantity> links = extractor.extractSearchParamQuantity(o1);
|
Set<ResourceIndexedSearchParamQuantity> links = extractor.extractSearchParamQuantity(o1);
|
||||||
ourLog.info("Links:\n {}", links.stream().map(t -> t.toString()).collect(Collectors.joining("\n ")));
|
ourLog.info("Links:\n {}", links.stream().map(t -> t.toString()).collect(Collectors.joining("\n ")));
|
||||||
assertEquals(4, links.size());
|
assertEquals(4, links.size());
|
||||||
|
@ -343,44 +335,44 @@ public class SearchParamExtractorR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtractComponentQuantityWithNormalizedQuantitySearchSupported() {
|
public void testExtractComponentQuantityWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
ModelConfig modelConfig = new ModelConfig();
|
ModelConfig modelConfig = new ModelConfig();
|
||||||
|
|
||||||
modelConfig.setNormalizedQuantitySearchSupported();
|
modelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
||||||
.setValue(new Quantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm").setValue(200));
|
.setValue(new Quantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm").setValue(200));
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
Set<ResourceIndexedSearchParamQuantityNormalized> links = extractor.extractSearchParamQuantityNormalized(o1);
|
Set<ResourceIndexedSearchParamQuantityNormalized> links = extractor.extractSearchParamQuantityNormalized(o1);
|
||||||
ourLog.info("Links:\n {}", links.stream().map(t -> t.toString()).collect(Collectors.joining("\n ")));
|
ourLog.info("Links:\n {}", links.stream().map(t -> t.toString()).collect(Collectors.joining("\n ")));
|
||||||
assertEquals(2, links.size());
|
assertEquals(2, links.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtractComponentQuantityValueWithNormalizedQuantitySearchSupported() {
|
public void testExtractComponentQuantityValueWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
ModelConfig modelConfig = new ModelConfig();
|
ModelConfig modelConfig = new ModelConfig();
|
||||||
|
|
||||||
modelConfig.setNormalizedQuantitySearchSupported();
|
modelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
|
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
||||||
.setValue(new Quantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm").setValue(200));
|
.setValue(new Quantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm").setValue(200));
|
||||||
|
|
||||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation").get("component-value-quantity");
|
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation").get("component-value-quantity");
|
||||||
|
|
||||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, new PartitionSettings(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(modelConfig, new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||||
List<String> list = extractor.extractParamValuesAsStrings(existingCodeSp, o1);
|
List<String> list = extractor.extractParamValuesAsStrings(existingCodeSp, o1);
|
||||||
|
|
||||||
assertEquals(1, list.size());
|
assertEquals(2, list.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MySearchParamRegistry implements ISearchParamRegistry {
|
private static class MySearchParamRegistry implements ISearchParamRegistry {
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,9 +449,4 @@ public class SearchParamExtractorR4Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() {
|
|
||||||
ourValidationSupport = new DefaultProfileValidationSupport(ourCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.search.PersistedJpaSearchFirstPageBundleProvider;
|
import ca.uhn.fhir.jpa.search.PersistedJpaSearchFirstPageBundleProvider;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
@ -62,8 +63,8 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test {
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void afterDisableExpunge() {
|
public void afterDisableExpunge() {
|
||||||
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeEnableExpunge() {
|
public void beforeEnableExpunge() {
|
||||||
|
@ -402,7 +403,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpungeSystemEverythingWithNormalizedQuantitySearchSupported() {
|
public void testExpungeSystemEverythingWithNormalizedQuantitySearchSupported() {
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
createStandardPatients();
|
createStandardPatients();
|
||||||
|
|
||||||
mySystemDao.expunge(new ExpungeOptions()
|
mySystemDao.expunge(new ExpungeOptions()
|
||||||
|
@ -424,7 +425,7 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpungeSystemEverythingWithNormalizedQuantityStorageSupported() {
|
public void testExpungeSystemEverythingWithNormalizedQuantityStorageSupported() {
|
||||||
myModelConfig.setNormalizedQuantityStorageSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
||||||
createStandardPatients();
|
createStandardPatients();
|
||||||
|
|
||||||
mySystemDao.expunge(new ExpungeOptions()
|
mySystemDao.expunge(new ExpungeOptions()
|
||||||
|
|
|
@ -47,6 +47,7 @@ import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
@ -217,9 +218,9 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||||
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
|
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
|
||||||
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(false);
|
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(false);
|
||||||
mySearchCoordinatorSvcRaw.cancelAllActiveSearches();
|
mySearchCoordinatorSvcRaw.cancelAllActiveSearches();
|
||||||
myDaoConfig.getModelConfig().setNormalizedQuantitySearchNotSupported();
|
myDaoConfig.getModelConfig().setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
|
|
||||||
myClient.unregisterInterceptor(myCapturingInterceptor);
|
myClient.unregisterInterceptor(myCapturingInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -4085,8 +4086,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported() throws Exception {
|
public void testSearchWithNormalizedQuantitySearchSupported() throws Exception {
|
||||||
|
|
||||||
myDaoConfig.getModelConfig().setNormalizedQuantitySearchSupported();
|
myDaoConfig.getModelConfig().setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
IIdType pid0;
|
IIdType pid0;
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -4167,8 +4168,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported_CombineUCUMOrNonUCUM() throws Exception {
|
public void testSearchWithNormalizedQuantitySearchSupported_CombineUCUMOrNonUCUM() throws Exception {
|
||||||
|
|
||||||
myDaoConfig.getModelConfig().setNormalizedQuantitySearchSupported();
|
myDaoConfig.getModelConfig().setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
IIdType pid0;
|
IIdType pid0;
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -4222,11 +4223,17 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||||
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// > 1m
|
String uri;
|
||||||
String uri = ourServerBase + "/Observation?value-quantity=" + UrlUtil.escapeUrlParam("100|http://unitsofmeasure.org|cm,100|http://foo|cm");
|
List<String> ids;
|
||||||
|
|
||||||
ourLog.info("uri = " + uri);
|
// With non-normalized
|
||||||
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
|
uri = ourServerBase + "/Observation?value-quantity=" + UrlUtil.escapeUrlParam("100|http://unitsofmeasure.org|cm,100|http://foo|cm");
|
||||||
|
ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
|
||||||
|
assertEquals(1, ids.size());
|
||||||
|
|
||||||
|
// With normalized
|
||||||
|
uri = ourServerBase + "/Observation?value-quantity=" + UrlUtil.escapeUrlParam("1|http://unitsofmeasure.org|m,100|http://foo|cm");
|
||||||
|
ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
|
||||||
assertEquals(2, ids.size());
|
assertEquals(2, ids.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6044,8 +6051,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWithNormalizedQuantitySearchSupported() throws Exception {
|
public void testUpdateWithNormalizedQuantitySearchSupported() throws Exception {
|
||||||
|
|
||||||
myDaoConfig.getModelConfig().setNormalizedQuantitySearchSupported();
|
myDaoConfig.getModelConfig().setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
IIdType pid0;
|
IIdType pid0;
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.config.TestR4Config;
|
import ca.uhn.fhir.jpa.config.TestR4Config;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||||
|
@ -103,8 +104,8 @@ public class InMemorySubscriptionMatcherR4Test {
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void after() throws Exception {
|
public void after() throws Exception {
|
||||||
myModelConfig.setNormalizedQuantitySearchNotSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertMatched(Resource resource, SearchParameterMap params) {
|
private void assertMatched(Resource resource, SearchParameterMap params) {
|
||||||
InMemoryMatchResult result = match(resource, params);
|
InMemoryMatchResult result = match(resource, params);
|
||||||
|
@ -249,8 +250,8 @@ public class InMemorySubscriptionMatcherR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported() {
|
public void testSearchWithNormalizedQuantitySearchSupported() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
|
@ -282,8 +283,8 @@ public class InMemorySubscriptionMatcherR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported_InvalidUCUMUnit() {
|
public void testSearchWithNormalizedQuantitySearchSupported_InvalidUCUMUnit() {
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://bar").setCode("foo")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://bar").setCode("foo")))
|
||||||
|
@ -298,8 +299,8 @@ public class InMemorySubscriptionMatcherR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported_NoSystem() {
|
public void testSearchWithNormalizedQuantitySearchSupported_NoSystem() {
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://bar").setCode("foo")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://bar").setCode("foo")))
|
||||||
|
@ -314,9 +315,9 @@ public class InMemorySubscriptionMatcherR4Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithNormalizedQuantitySearchSupported_NotUcumSystem() {
|
public void testSearchWithNormalizedQuantitySearchSupported_NotUcumSystem() {
|
||||||
|
|
||||||
myModelConfig.setNormalizedQuantitySearchSupported();
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||||
|
|
||||||
Observation o1 = new Observation();
|
Observation o1 = new Observation();
|
||||||
o1.addComponent()
|
o1.addComponent()
|
||||||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("cm")))
|
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("cm")))
|
||||||
|
|
|
@ -22,14 +22,14 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
||||||
|
|
||||||
public enum ColumnTypeEnum {
|
public enum ColumnTypeEnum {
|
||||||
|
|
||||||
LONG,
|
LONG,
|
||||||
STRING,
|
STRING,
|
||||||
DATE_ONLY,
|
DATE_ONLY,
|
||||||
DATE_TIMESTAMP,
|
DATE_TIMESTAMP,
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
FLOAT,
|
FLOAT,
|
||||||
INT,
|
INT,
|
||||||
BLOB,
|
BLOB,
|
||||||
CLOB
|
CLOB,
|
||||||
|
DOUBLE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,14 @@ public class ColumnTypeToDriverTypeToSqlType {
|
||||||
setColumnType(ColumnTypeEnum.FLOAT, DriverTypeEnum.ORACLE_12C, "float");
|
setColumnType(ColumnTypeEnum.FLOAT, DriverTypeEnum.ORACLE_12C, "float");
|
||||||
setColumnType(ColumnTypeEnum.FLOAT, DriverTypeEnum.POSTGRES_9_4, "float");
|
setColumnType(ColumnTypeEnum.FLOAT, DriverTypeEnum.POSTGRES_9_4, "float");
|
||||||
|
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.H2_EMBEDDED, "double");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.DERBY_EMBEDDED, "double");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.MARIADB_10_1, "double precision");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.MYSQL_5_7, "double precision");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.MSSQL_2012, "double precision");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.ORACLE_12C, "double precision");
|
||||||
|
setColumnType(ColumnTypeEnum.DOUBLE, DriverTypeEnum.POSTGRES_9_4, "float8");
|
||||||
|
|
||||||
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.H2_EMBEDDED, "bigint");
|
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.H2_EMBEDDED, "bigint");
|
||||||
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.DERBY_EMBEDDED, "bigint");
|
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.DERBY_EMBEDDED, "bigint");
|
||||||
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.MARIADB_10_1, "bigint");
|
setColumnType(ColumnTypeEnum.LONG, DriverTypeEnum.MARIADB_10_1, "bigint");
|
||||||
|
|
|
@ -119,6 +119,10 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
||||||
.addForeignKey("20210111.3", "FKRCJOVMUH5KC0O6FVBLE319PYV")
|
.addForeignKey("20210111.3", "FKRCJOVMUH5KC0O6FVBLE319PYV")
|
||||||
.toColumn("RES_ID")
|
.toColumn("RES_ID")
|
||||||
.references("HFJ_RESOURCE", "RES_ID");
|
.references("HFJ_RESOURCE", "RES_ID");
|
||||||
|
|
||||||
|
Builder.BuilderWithTableName quantityTable = version.onTable("HFJ_SPIDX_QUANTITY");
|
||||||
|
quantityTable.modifyColumn("20210116.1", "SP_VALUE").nullable().failureAllowed().withType(ColumnTypeEnum.DOUBLE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void init520() {
|
protected void init520() {
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class ModelConfig {
|
||||||
private IPrimitiveType<Date> myPeriodIndexEndOfTime;
|
private IPrimitiveType<Date> myPeriodIndexEndOfTime;
|
||||||
|
|
||||||
private NormalizedQuantitySearchLevel myNormalizedQuantitySearchLevel;
|
private NormalizedQuantitySearchLevel myNormalizedQuantitySearchLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -576,6 +576,47 @@ public class ModelConfig {
|
||||||
myPeriodIndexEndOfTime = thePeriodIndexEndOfTime;
|
myPeriodIndexEndOfTime = thePeriodIndexEndOfTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles whether Quantity searches support value normalization when using valid UCUM coded values.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The default value is {@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED} which is current behavior.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Here is the UCUM service support level
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED}, default, Quantity is stored in {@link ResourceIndexedSearchParamQuantity} only and it is used by searching.</li>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_STORAGE_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, but {@link ResourceIndexedSearchParamQuantity} is used by searching.</li>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, {@link ResourceIndexedSearchParamQuantityNormalized} is used by searching.</li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 5.3.0
|
||||||
|
*/
|
||||||
|
public NormalizedQuantitySearchLevel getNormalizedQuantitySearchLevel() {
|
||||||
|
return myNormalizedQuantitySearchLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles whether Quantity searches support value normalization when using valid UCUM coded values.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The default value is {@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED} which is current behavior.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Here is the UCUM service support level
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED}, default, Quantity is stored in {@link ResourceIndexedSearchParamQuantity} only and it is used by searching.</li>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_STORAGE_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, but {@link ResourceIndexedSearchParamQuantity} is used by searching.</li>
|
||||||
|
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, {@link ResourceIndexedSearchParamQuantityNormalized} is used by searching.</li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 5.3.0
|
||||||
|
*/
|
||||||
|
public void setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel theNormalizedQuantitySearchLevel) {
|
||||||
|
myNormalizedQuantitySearchLevel = theNormalizedQuantitySearchLevel;
|
||||||
|
}
|
||||||
|
|
||||||
private static void validateTreatBaseUrlsAsLocal(String theUrl) {
|
private static void validateTreatBaseUrlsAsLocal(String theUrl) {
|
||||||
Validate.notBlank(theUrl, "Base URL must not be null or empty");
|
Validate.notBlank(theUrl, "Base URL must not be null or empty");
|
||||||
|
@ -589,43 +630,4 @@ public class ModelConfig {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the UCUM service support level
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The default value is {@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED} which is current behavior.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Here is the UCUM service support level
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED}, default, Quantity is stored in {@link ResourceIndexedSearchParamQuantity} only and it is used by searching.</li>
|
|
||||||
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_STORAGE_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, but {@link ResourceIndexedSearchParamQuantity} is used by searching.</li>
|
|
||||||
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_SUPPORTED}, Quantity is stored in both {@link ResourceIndexedSearchParamQuantity} and {@link ResourceIndexedSearchParamQuantityNormalized}, {@link ResourceIndexedSearchParamQuantityNormalized} is used by searching.</li>
|
|
||||||
* <li>{@link NormalizedQuantitySearchLevel#NORMALIZED_QUANTITY_SEARCH_FULL_SUPPORTED}, Quantity is stored in only in {@link ResourceIndexedSearchParamQuantityNormalized}, {@link ResourceIndexedSearchParamQuantityNormalized} is used by searching. NOTE: this option is not supported yet.</li>
|
|
||||||
* </ul>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @since 5.3.0
|
|
||||||
*/
|
|
||||||
public NormalizedQuantitySearchLevel getNormalizedQuantitySearchLevel() {
|
|
||||||
return myNormalizedQuantitySearchLevel;
|
|
||||||
}
|
|
||||||
public void setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel theNormalizedQuantitySearchLevel) {
|
|
||||||
myNormalizedQuantitySearchLevel = theNormalizedQuantitySearchLevel;
|
|
||||||
}
|
|
||||||
public boolean isNormalizedQuantitySearchSupported() {
|
|
||||||
return myNormalizedQuantitySearchLevel.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
|
||||||
}
|
|
||||||
public boolean isNormalizedQuantityStorageSupported() {
|
|
||||||
return myNormalizedQuantitySearchLevel.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED);
|
|
||||||
}
|
|
||||||
public void setNormalizedQuantitySearchNotSupported() {
|
|
||||||
myNormalizedQuantitySearchLevel = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
public void setNormalizedQuantityStorageSupported() {
|
|
||||||
myNormalizedQuantitySearchLevel = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED;
|
|
||||||
}
|
|
||||||
public void setNormalizedQuantitySearchSupported() {
|
|
||||||
myNormalizedQuantitySearchLevel = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,5 +53,6 @@ public enum NormalizedQuantitySearchLevel {
|
||||||
* The existing non normalized quantity will be not supported
|
* The existing non normalized quantity will be not supported
|
||||||
* NOTE: this option is not supported in this release
|
* NOTE: this option is not supported in this release
|
||||||
*/
|
*/
|
||||||
|
// When this is enabled, we can enable testSortByQuantityWithNormalizedQuantitySearchFullSupported()
|
||||||
//NORMALIZED_QUANTITY_SEARCH_FULL_SUPPORTED,
|
//NORMALIZED_QUANTITY_SEARCH_FULL_SUPPORTED,
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class ResourceIndexedSearchParamQuantity extends ResourceIndexedSearchPar
|
||||||
|
|
||||||
@Column(name = "SP_VALUE", nullable = true)
|
@Column(name = "SP_VALUE", nullable = true)
|
||||||
@ScaledNumberField
|
@ScaledNumberField
|
||||||
public BigDecimal myValue;
|
public Double myValue;
|
||||||
|
|
||||||
public ResourceIndexedSearchParamQuantity() {
|
public ResourceIndexedSearchParamQuantity() {
|
||||||
super();
|
super();
|
||||||
|
@ -99,11 +99,11 @@ public class ResourceIndexedSearchParamQuantity extends ResourceIndexedSearchPar
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getValue() {
|
public BigDecimal getValue() {
|
||||||
return myValue;
|
return myValue != null ? new BigDecimal(myValue) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceIndexedSearchParamQuantity setValue(BigDecimal theValue) {
|
public ResourceIndexedSearchParamQuantity setValue(BigDecimal theValue) {
|
||||||
myValue = theValue;
|
myValue = theValue != null ? theValue.doubleValue() : null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import org.fhir.ucum.Pair;
|
import org.fhir.ucum.Pair;
|
||||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
|
|
||||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ScaledNumberField;
|
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ScaledNumberField;
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,23 +83,14 @@ public class ResourceIndexedSearchParamQuantityNormalized extends ResourceIndexe
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceIndexedSearchParamQuantityNormalized(PartitionSettings thePartitionSettings, String theResourceType, String theParamName, BigDecimal theValue, String theSystem, String theUnits) {
|
public ResourceIndexedSearchParamQuantityNormalized(PartitionSettings thePartitionSettings, String theResourceType, String theParamName, double theValue, String theSystem, String theUnits) {
|
||||||
this();
|
this();
|
||||||
setPartitionSettings(thePartitionSettings);
|
setPartitionSettings(thePartitionSettings);
|
||||||
setResourceType(theResourceType);
|
setResourceType(theResourceType);
|
||||||
setParamName(theParamName);
|
setParamName(theParamName);
|
||||||
setSystem(theSystem);
|
setSystem(theSystem);
|
||||||
|
setValue(theValue);
|
||||||
//-- convert the value/unit to the canonical form if any, otherwise store the original value/units pair
|
setUnits(theUnits);
|
||||||
Pair canonicalForm = UcumServiceUtil.getCanonicalForm(theSystem, theValue, theUnits);
|
|
||||||
if (canonicalForm != null) {
|
|
||||||
setValue(Double.parseDouble(canonicalForm.getValue().asDecimal()));
|
|
||||||
setUnits(canonicalForm.getCode());
|
|
||||||
} else {
|
|
||||||
setValue(theValue);
|
|
||||||
setUnits(theUnits);
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,17 +113,13 @@ public class ResourceIndexedSearchParamQuantityNormalized extends ResourceIndexe
|
||||||
public ResourceIndexedSearchParamQuantityNormalized setValue(Double theValue) {
|
public ResourceIndexedSearchParamQuantityNormalized setValue(Double theValue) {
|
||||||
myValue = theValue;
|
myValue = theValue;
|
||||||
return this;
|
return this;
|
||||||
}
|
|
||||||
public void setValue(BigDecimal theValue) {
|
|
||||||
if (theValue != null)
|
|
||||||
myValue = theValue.doubleValue();
|
|
||||||
}
|
}
|
||||||
public BigDecimal getValueBigDecimal() {
|
|
||||||
if (myValue == null)
|
public ResourceIndexedSearchParamQuantityNormalized setValue(double theValue) {
|
||||||
return null;
|
myValue = theValue;
|
||||||
return new BigDecimal(myValue);
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-- myId
|
//-- myId
|
||||||
@Override
|
@Override
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.model.util;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
import org.fhir.ucum.Decimal;
|
import org.fhir.ucum.Decimal;
|
||||||
import org.fhir.ucum.Pair;
|
import org.fhir.ucum.Pair;
|
||||||
import org.fhir.ucum.UcumEssenceService;
|
import org.fhir.ucum.UcumEssenceService;
|
||||||
|
@ -32,6 +33,8 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ca.uhn.fhir.util.ClasspathUtil;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It's a wrapper of UcumEssenceService
|
* It's a wrapper of UcumEssenceService
|
||||||
*
|
*
|
||||||
|
@ -85,7 +88,7 @@ public class UcumServiceUtil {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
init();
|
init();
|
||||||
Pair theCanonicalPair = null;
|
Pair theCanonicalPair;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Decimal theDecimal = new Decimal(theValue.toPlainString(), theValue.precision());
|
Decimal theDecimal = new Decimal(theValue.toPlainString(), theValue.precision());
|
||||||
|
@ -97,4 +100,19 @@ public class UcumServiceUtil {
|
||||||
return theCanonicalPair;
|
return theCanonicalPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static QuantityParam toCanonicalQuantityOrNull(QuantityParam theQuantityParam) {
|
||||||
|
Pair canonicalForm = getCanonicalForm(theQuantityParam.getSystem(), theQuantityParam.getValue(), theQuantityParam.getUnits());
|
||||||
|
if (canonicalForm != null) {
|
||||||
|
BigDecimal valueValue = new BigDecimal(canonicalForm.getValue().asDecimal());
|
||||||
|
String unitsValue = canonicalForm.getCode();
|
||||||
|
return new QuantityParam()
|
||||||
|
.setSystem(theQuantityParam.getSystem())
|
||||||
|
.setValue(valueValue)
|
||||||
|
.setUnits(unitsValue)
|
||||||
|
.setPrefix(theQuantityParam.getPrefix());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,13 @@
|
||||||
package ca.uhn.fhir.jpa.model.entity;
|
package ca.uhn.fhir.jpa.model.entity;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
|
||||||
public class ResourceIndexedSearchParamQuantityNormalizedTest {
|
public class ResourceIndexedSearchParamQuantityNormalizedTest {
|
||||||
|
|
||||||
private ResourceIndexedSearchParamQuantityNormalized createParam(String theParamName, String theValue, String theSystem, String theUnits) {
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized token = new ResourceIndexedSearchParamQuantityNormalized(new PartitionSettings(), "Observation", theParamName, new BigDecimal(theValue), theSystem, theUnits);
|
|
||||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHashFunctions() {
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized token = createParam("Quanity", "123.001", UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm");
|
|
||||||
token.calculateHashes();
|
|
||||||
|
|
||||||
// Make sure our hashing function gives consistent results
|
|
||||||
assertEquals(5219730978980909111L, token.getHashIdentity().longValue());
|
|
||||||
assertEquals(-2454931617586657338L, token.getHashIdentityAndUnits().longValue());
|
|
||||||
assertEquals(878263047209296227L, token.getHashIdentitySystemAndUnits().longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() {
|
public void testEquals() {
|
||||||
|
@ -46,37 +25,5 @@ public class ResourceIndexedSearchParamQuantityNormalizedTest {
|
||||||
assertNotEquals(val1, "");
|
assertNotEquals(val1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUcum() {
|
|
||||||
|
|
||||||
//-- system is ucum
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized token1 = createParam("Quanity", "123.001", UcumServiceUtil.UCUM_CODESYSTEM_URL, "cm");
|
|
||||||
token1.calculateHashes();
|
|
||||||
|
|
||||||
assertEquals("m", token1.getUnits());
|
|
||||||
assertEquals(Double.parseDouble("1.23001"), token1.getValue());
|
|
||||||
|
|
||||||
//-- small number
|
|
||||||
token1 = createParam("Quanity", "0.000001", UcumServiceUtil.UCUM_CODESYSTEM_URL, "mm");
|
|
||||||
token1.calculateHashes();
|
|
||||||
|
|
||||||
assertEquals("m", token1.getUnits());
|
|
||||||
assertEquals(Double.parseDouble("0.000000001"), token1.getValue());
|
|
||||||
|
|
||||||
|
|
||||||
// -- non ucum system
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized token2 = createParam("Quanity", "123.001", "http://abc.org", "cm");
|
|
||||||
token2.calculateHashes();
|
|
||||||
|
|
||||||
assertEquals("cm", token2.getUnits());
|
|
||||||
assertEquals(Double.parseDouble("123.001"), token2.getValue());
|
|
||||||
|
|
||||||
// -- unsupported ucum code
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized token3 = createParam("Quanity", "123.001", UcumServiceUtil.UCUM_CODESYSTEM_URL, "unknown");
|
|
||||||
token3.calculateHashes();
|
|
||||||
|
|
||||||
assertEquals("unknown", token3.getUnits());
|
|
||||||
assertEquals(Double.parseDouble("123.001"), token3.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||||
|
@ -38,6 +39,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||||
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||||
|
@ -49,7 +51,7 @@ import com.google.common.collect.Sets;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hibernate.search.engine.spatial.GeoPoint;
|
import org.fhir.ucum.Pair;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
|
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
|
||||||
|
@ -78,7 +80,6 @@ import java.util.TreeSet;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.searchparam.extractor.GeopointNormalizer.normalizeLongitude;
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.trim;
|
import static org.apache.commons.lang3.StringUtils.trim;
|
||||||
|
@ -199,12 +200,16 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
break;
|
break;
|
||||||
case REFERENCE:
|
case REFERENCE:
|
||||||
extractor = createReferenceExtractor();
|
extractor = createReferenceExtractor();
|
||||||
return extractReferenceParamsAsQueryTokens(theSearchParam, theResource, extractor);
|
break;
|
||||||
case QUANTITY:
|
case QUANTITY:
|
||||||
if (myModelConfig.isNormalizedQuantitySearchSupported())
|
if (myModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
|
||||||
extractor = createQuantityNormalizedExtractor(theResource);
|
extractor = new CompositeExtractor(
|
||||||
else
|
createQuantityExtractor(theResource),
|
||||||
|
createQuantityNormalizedExtractor(theResource)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
extractor = createQuantityExtractor(theResource);
|
extractor = createQuantityExtractor(theResource);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case URI:
|
case URI:
|
||||||
extractor = createUriExtractor(theResource);
|
extractor = createUriExtractor(theResource);
|
||||||
|
@ -216,6 +221,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Type " + theSearchParam.getParamType() + " not supported for extraction");
|
throw new UnsupportedOperationException("Type " + theSearchParam.getParamType() + " not supported for extraction");
|
||||||
}
|
}
|
||||||
|
|
||||||
return extractParamsAsQueryTokens(theSearchParam, theResource, extractor);
|
return extractParamsAsQueryTokens(theSearchParam, theResource, extractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,14 +383,14 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.QUANTITY);
|
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.QUANTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> extractSearchParamQuantityNormalized(IBaseResource theResource) {
|
public SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> extractSearchParamQuantityNormalized(IBaseResource theResource) {
|
||||||
IExtractor<ResourceIndexedSearchParamQuantityNormalized> extractor = createQuantityNormalizedExtractor(theResource);
|
IExtractor<ResourceIndexedSearchParamQuantityNormalized> extractor = createQuantityNormalizedExtractor(theResource);
|
||||||
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.QUANTITY);
|
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.QUANTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IExtractor<ResourceIndexedSearchParamQuantity> createQuantityExtractor(IBaseResource theResource) {
|
private IExtractor<ResourceIndexedSearchParamQuantity> createQuantityExtractor(IBaseResource theResource) {
|
||||||
return (params, searchParam, value, path) -> {
|
return (params, searchParam, value, path) -> {
|
||||||
if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
||||||
return;
|
return;
|
||||||
|
@ -394,7 +400,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
String resourceType = toRootTypeName(theResource);
|
String resourceType = toRootTypeName(theResource);
|
||||||
switch (nextType) {
|
switch (nextType) {
|
||||||
case "Quantity":
|
case "Quantity":
|
||||||
addQuantity_Quantity(resourceType, params, searchParam, value);
|
addQuantity_Quantity(resourceType, params, searchParam, value);
|
||||||
break;
|
break;
|
||||||
case "Money":
|
case "Money":
|
||||||
addQuantity_Money(resourceType, params, searchParam, value);
|
addQuantity_Money(resourceType, params, searchParam, value);
|
||||||
|
@ -406,11 +412,11 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private IExtractor<ResourceIndexedSearchParamQuantityNormalized> createQuantityNormalizedExtractor(IBaseResource theResource) {
|
private IExtractor<ResourceIndexedSearchParamQuantityNormalized> createQuantityNormalizedExtractor(IBaseResource theResource) {
|
||||||
|
|
||||||
return (params, searchParam, value, path) -> {
|
return (params, searchParam, value, path) -> {
|
||||||
if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
||||||
return;
|
return;
|
||||||
|
@ -434,7 +440,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
public SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
||||||
IExtractor<ResourceIndexedSearchParamString> extractor = createStringExtractor(theResource);
|
IExtractor<ResourceIndexedSearchParamString> extractor = createStringExtractor(theResource);
|
||||||
|
@ -546,24 +552,31 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
||||||
|
|
||||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(myPartitionSettings, theResourceType, theSearchParam.getName(), nextValueValue, system, code);
|
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(myPartitionSettings, theResourceType, theSearchParam.getName(), nextValueValue, system, code);
|
||||||
|
|
||||||
theParams.add(nextEntity);
|
theParams.add(nextEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addQuantity_QuantityNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addQuantity_QuantityNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
Optional<IPrimitiveType<BigDecimal>> valueField = myQuantityValueValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IPrimitiveType<BigDecimal>> valueField = myQuantityValueValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||||
BigDecimal nextValueValue = valueField.get().getValue();
|
BigDecimal nextValueValue = valueField.get().getValue();
|
||||||
String system = extractValueAsString(myQuantitySystemValueChild, theValue);
|
String system = extractValueAsString(myQuantitySystemValueChild, theValue);
|
||||||
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
||||||
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized nextEntity = new ResourceIndexedSearchParamQuantityNormalized(myPartitionSettings, theResourceType, theSearchParam.getName(), nextValueValue, system, code);
|
//-- convert the value/unit to the canonical form if any
|
||||||
theParams.add(nextEntity);
|
Pair canonicalForm = UcumServiceUtil.getCanonicalForm(system, nextValueValue, code);
|
||||||
|
if (canonicalForm != null) {
|
||||||
|
double canonicalValue = Double.parseDouble(canonicalForm.getValue().asDecimal());
|
||||||
|
String canonicalUnits = canonicalForm.getCode();
|
||||||
|
ResourceIndexedSearchParamQuantityNormalized nextEntity = new ResourceIndexedSearchParamQuantityNormalized(myPartitionSettings, theResourceType, theSearchParam.getName(), canonicalValue, system, canonicalUnits);
|
||||||
|
theParams.add(nextEntity);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addQuantity_Money(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addQuantity_Money(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
Optional<IPrimitiveType<BigDecimal>> valueField = myMoneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IPrimitiveType<BigDecimal>> valueField = myMoneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||||
|
@ -572,14 +585,14 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
String nextValueString = "urn:iso:std:iso:4217";
|
String nextValueString = "urn:iso:std:iso:4217";
|
||||||
String nextValueCode = extractValueAsString(myMoneyCurrencyChild, theValue);
|
String nextValueCode = extractValueAsString(myMoneyCurrencyChild, theValue);
|
||||||
String searchParamName = theSearchParam.getName();
|
String searchParamName = theSearchParam.getName();
|
||||||
|
|
||||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(myPartitionSettings, theResourceType, searchParamName, nextValueValue, nextValueString, nextValueCode);
|
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(myPartitionSettings, theResourceType, searchParamName, nextValueValue, nextValueString, nextValueCode);
|
||||||
theParams.add(nextEntity);
|
theParams.add(nextEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addQuantity_MoneyNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addQuantity_MoneyNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
Optional<IPrimitiveType<BigDecimal>> valueField = myMoneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IPrimitiveType<BigDecimal>> valueField = myMoneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||||
BigDecimal nextValueValue = valueField.get().getValue();
|
BigDecimal nextValueValue = valueField.get().getValue();
|
||||||
|
@ -587,22 +600,22 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
String nextValueString = "urn:iso:std:iso:4217";
|
String nextValueString = "urn:iso:std:iso:4217";
|
||||||
String nextValueCode = extractValueAsString(myMoneyCurrencyChild, theValue);
|
String nextValueCode = extractValueAsString(myMoneyCurrencyChild, theValue);
|
||||||
String searchParamName = theSearchParam.getName();
|
String searchParamName = theSearchParam.getName();
|
||||||
|
|
||||||
ResourceIndexedSearchParamQuantityNormalized nextEntityNormalized = new ResourceIndexedSearchParamQuantityNormalized(myPartitionSettings, theResourceType, searchParamName, nextValueValue, nextValueString, nextValueCode);
|
ResourceIndexedSearchParamQuantityNormalized nextEntityNormalized = new ResourceIndexedSearchParamQuantityNormalized(myPartitionSettings, theResourceType, searchParamName, nextValueValue.doubleValue(), nextValueString, nextValueCode);
|
||||||
theParams.add(nextEntityNormalized);
|
theParams.add(nextEntityNormalized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addQuantity_Range(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addQuantity_Range(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
Optional<IBase> low = myRangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IBase> low = myRangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
low.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
low.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
||||||
|
|
||||||
Optional<IBase> high = myRangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IBase> high = myRangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
high.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
high.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addQuantity_RangeNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addQuantity_RangeNormalized(String theResourceType, Set<ResourceIndexedSearchParamQuantityNormalized> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
Optional<IBase> low = myRangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IBase> low = myRangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
low.ifPresent(theIBase -> addQuantity_QuantityNormalized(theResourceType, theParams, theSearchParam, theIBase));
|
low.ifPresent(theIBase -> addQuantity_QuantityNormalized(theResourceType, theParams, theSearchParam, theIBase));
|
||||||
|
@ -610,7 +623,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
Optional<IBase> high = myRangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
Optional<IBase> high = myRangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||||
high.ifPresent(theIBase -> addQuantity_QuantityNormalized(theResourceType, theParams, theSearchParam, theIBase));
|
high.ifPresent(theIBase -> addQuantity_QuantityNormalized(theResourceType, theParams, theSearchParam, theIBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToken_Identifier(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addToken_Identifier(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
String system = extractValueAsString(myIdentifierSystemValueChild, theValue);
|
String system = extractValueAsString(myIdentifierSystemValueChild, theValue);
|
||||||
String value = extractValueAsString(myIdentifierValueValueChild, theValue);
|
String value = extractValueAsString(myIdentifierValueValueChild, theValue);
|
||||||
|
@ -1163,11 +1176,27 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface IExtractor<T> {
|
private interface IExtractor<T> {
|
||||||
|
|
||||||
|
|
||||||
void extract(SearchParamSet<T> theParams, RuntimeSearchParam theSearchParam, IBase theValue, String thePath);
|
void extract(SearchParamSet<T> theParams, RuntimeSearchParam theSearchParam, IBase theValue, String thePath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class CompositeExtractor<T> implements IExtractor<T> {
|
||||||
|
|
||||||
|
private final IExtractor<T> myExtractor0;
|
||||||
|
private final IExtractor<T> myExtractor1;
|
||||||
|
|
||||||
|
private CompositeExtractor(IExtractor<T> theExtractor0, IExtractor<T> theExtractor1) {
|
||||||
|
myExtractor0 = theExtractor0;
|
||||||
|
myExtractor1 = theExtractor1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extract(SearchParamSet<T> theParams, RuntimeSearchParam theSearchParam, IBase theValue, String thePath) {
|
||||||
|
myExtractor0.extract(theParams, theSearchParam, theValue, thePath);
|
||||||
|
myExtractor1.extract(theParams, theSearchParam, theValue, thePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ResourceLinkExtractor implements IExtractor<PathAndRef> {
|
private class ResourceLinkExtractor implements IExtractor<PathAndRef> {
|
||||||
|
|
||||||
private PathAndRef myPathAndRef = null;
|
private PathAndRef myPathAndRef = null;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
|
@ -36,9 +37,14 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -51,6 +57,7 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.compare;
|
import static org.apache.commons.lang3.StringUtils.compare;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
@ -158,21 +165,30 @@ public final class ResourceIndexedSearchParams {
|
||||||
return myPopulatedResourceLinkParameters;
|
return myPopulatedResourceLinkParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matchParam(ModelConfig theModelConfig, String theResourceName, String theParamName, RuntimeSearchParam theParamDef, IQueryParameterType theParam) {
|
public boolean matchParam(ModelConfig theModelConfig, String theResourceName, String theParamName, RuntimeSearchParam theParamDef, IQueryParameterType theValue) {
|
||||||
|
|
||||||
if (theParamDef == null) {
|
if (theParamDef == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Collection<? extends BaseResourceIndexedSearchParam> resourceParams;
|
Collection<? extends BaseResourceIndexedSearchParam> resourceParams = null;
|
||||||
|
IQueryParameterType value = theValue;
|
||||||
switch (theParamDef.getParamType()) {
|
switch (theParamDef.getParamType()) {
|
||||||
case TOKEN:
|
case TOKEN:
|
||||||
resourceParams = myTokenParams;
|
resourceParams = myTokenParams;
|
||||||
break;
|
break;
|
||||||
case QUANTITY:
|
case QUANTITY:
|
||||||
if (theModelConfig.isNormalizedQuantitySearchSupported())
|
if (theModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
|
||||||
resourceParams = myQuantityNormalizedParams;
|
QuantityParam quantity = QuantityParam.toQuantityParam(theValue);
|
||||||
else
|
QuantityParam normalized = UcumServiceUtil.toCanonicalQuantityOrNull(quantity);
|
||||||
resourceParams = myQuantityParams;
|
if (normalized != null) {
|
||||||
|
resourceParams = myQuantityNormalizedParams;
|
||||||
|
value = normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resourceParams == null) {
|
||||||
|
resourceParams = myQuantityParams;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
resourceParams = myStringParams;
|
resourceParams = myStringParams;
|
||||||
|
@ -187,7 +203,7 @@ public final class ResourceIndexedSearchParams {
|
||||||
resourceParams = myDateParams;
|
resourceParams = myDateParams;
|
||||||
break;
|
break;
|
||||||
case REFERENCE:
|
case REFERENCE:
|
||||||
return matchResourceLinks(theModelConfig, theResourceName, theParamName, theParam, theParamDef.getPath());
|
return matchResourceLinks(theModelConfig, theResourceName, theParamName, value, theParamDef.getPath());
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
case HAS:
|
case HAS:
|
||||||
case SPECIAL:
|
case SPECIAL:
|
||||||
|
@ -197,11 +213,16 @@ public final class ResourceIndexedSearchParams {
|
||||||
if (resourceParams == null) {
|
if (resourceParams == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Predicate<BaseResourceIndexedSearchParam> namedParamPredicate = param ->
|
|
||||||
param.getParamName().equalsIgnoreCase(theParamName) &&
|
|
||||||
param.matches(theParam);
|
|
||||||
|
|
||||||
return resourceParams.stream().anyMatch(namedParamPredicate);
|
for (BaseResourceIndexedSearchParam nextParam : resourceParams) {
|
||||||
|
if (nextParam.getParamName().equalsIgnoreCase(theParamName)) {
|
||||||
|
if (nextParam.matches(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,10 +296,7 @@ public final class ResourceIndexedSearchParams {
|
||||||
public void findMissingSearchParams(PartitionSettings thePartitionSettings, ModelConfig theModelConfig, ResourceTable theEntity, Set<Entry<String, RuntimeSearchParam>> theActiveSearchParams) {
|
public void findMissingSearchParams(PartitionSettings thePartitionSettings, ModelConfig theModelConfig, ResourceTable theEntity, Set<Entry<String, RuntimeSearchParam>> theActiveSearchParams) {
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.STRING, myStringParams);
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.STRING, myStringParams);
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.NUMBER, myNumberParams);
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.NUMBER, myNumberParams);
|
||||||
if (theModelConfig.isNormalizedQuantitySearchSupported())
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.QUANTITY, myQuantityParams);
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.QUANTITY, myQuantityNormalizedParams);
|
|
||||||
else
|
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.QUANTITY, myQuantityParams);
|
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.DATE, myDateParams);
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.DATE, myDateParams);
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.URI, myUriParams);
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.URI, myUriParams);
|
||||||
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.TOKEN, myTokenParams);
|
findMissingSearchParams(thePartitionSettings, theModelConfig, theEntity, theActiveSearchParams, RestSearchParameterTypeEnum.TOKEN, myTokenParams);
|
||||||
|
@ -309,10 +327,7 @@ public final class ResourceIndexedSearchParams {
|
||||||
param = new ResourceIndexedSearchParamNumber();
|
param = new ResourceIndexedSearchParamNumber();
|
||||||
break;
|
break;
|
||||||
case QUANTITY:
|
case QUANTITY:
|
||||||
if (theModelConfig.isNormalizedQuantitySearchSupported())
|
param = new ResourceIndexedSearchParamQuantity();
|
||||||
param = new ResourceIndexedSearchParamQuantityNormalized();
|
|
||||||
else
|
|
||||||
param = new ResourceIndexedSearchParamQuantity();
|
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
param = new ResourceIndexedSearchParamString()
|
param = new ResourceIndexedSearchParamString()
|
||||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
|
@ -50,9 +49,9 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
||||||
|
|
||||||
// This constructor is used by tests
|
// This constructor is used by tests
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public SearchParamExtractorDstu3(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) {
|
public SearchParamExtractorDstu3(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
||||||
initFhirPathEngine(theValidationSupport);
|
initFhirPathEngine();
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +74,12 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
||||||
public void start() {
|
public void start() {
|
||||||
super.start();
|
super.start();
|
||||||
if (myFhirPathEngine == null) {
|
if (myFhirPathEngine == null) {
|
||||||
IValidationSupport support = myApplicationContext.getBean(IValidationSupport.class);
|
initFhirPathEngine();
|
||||||
initFhirPathEngine(support);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initFhirPathEngine(IValidationSupport theSupport) {
|
public void initFhirPathEngine() {
|
||||||
IWorkerContext worker = new HapiWorkerContext(getContext(), theSupport);
|
IWorkerContext worker = new HapiWorkerContext(getContext(), getContext().getValidationSupport());
|
||||||
myFhirPathEngine = new FHIRPathEngine(worker);
|
myFhirPathEngine = new FHIRPathEngine(worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
|
@ -62,9 +61,9 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
// This constructor is used by tests
|
// This constructor is used by tests
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public SearchParamExtractorR4(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) {
|
public SearchParamExtractorR4(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
||||||
initFhirPath(theValidationSupport);
|
initFhirPath();
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,13 +81,12 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
public void start() {
|
public void start() {
|
||||||
super.start();
|
super.start();
|
||||||
if (myFhirPathEngine == null) {
|
if (myFhirPathEngine == null) {
|
||||||
IValidationSupport support = myApplicationContext.getBean(IValidationSupport.class);
|
initFhirPath();
|
||||||
initFhirPath(support);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initFhirPath(IValidationSupport theSupport) {
|
public void initFhirPath() {
|
||||||
IWorkerContext worker = new HapiWorkerContext(getContext(), theSupport);
|
IWorkerContext worker = new HapiWorkerContext(getContext(), getContext().getValidationSupport());
|
||||||
myFhirPathEngine = new FHIRPathEngine(worker);
|
myFhirPathEngine = new FHIRPathEngine(worker);
|
||||||
myFhirPathEngine.setHostServices(new SearchParamExtractorR4HostServices());
|
myFhirPathEngine.setHostServices(new SearchParamExtractorR4HostServices());
|
||||||
}
|
}
|
||||||
|
@ -96,7 +94,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
private static class SearchParamExtractorR4HostServices implements FHIRPathEngine.IEvaluationContext {
|
private static class SearchParamExtractorR4HostServices implements FHIRPathEngine.IEvaluationContext {
|
||||||
|
|
||||||
private Map<String, Base> myResourceTypeToStub = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, Base> myResourceTypeToStub = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException {
|
public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException {
|
||||||
|
|
|
@ -21,8 +21,6 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
|
@ -58,9 +56,9 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
||||||
/**
|
/**
|
||||||
* Constructor for unit tests
|
* Constructor for unit tests
|
||||||
*/
|
*/
|
||||||
public SearchParamExtractorR5(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, DefaultProfileValidationSupport theDefaultProfileValidationSupport, ISearchParamRegistry theSearchParamRegistry) {
|
public SearchParamExtractorR5(ModelConfig theModelConfig, PartitionSettings thePartitionSettings, FhirContext theCtx, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
super(theModelConfig, thePartitionSettings, theCtx, theSearchParamRegistry);
|
||||||
initFhirPath(theDefaultProfileValidationSupport);
|
initFhirPath();
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,13 +67,12 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
||||||
public void start() {
|
public void start() {
|
||||||
super.start();
|
super.start();
|
||||||
if (myFhirPathEngine == null) {
|
if (myFhirPathEngine == null) {
|
||||||
IValidationSupport support = myApplicationContext.getBean(IValidationSupport.class);
|
initFhirPath();
|
||||||
initFhirPath(support);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initFhirPath(IValidationSupport theSupport) {
|
public void initFhirPath() {
|
||||||
IWorkerContext worker = new HapiWorkerContext(getContext(), theSupport);
|
IWorkerContext worker = new HapiWorkerContext(getContext(), getContext().getValidationSupport());
|
||||||
myFhirPathEngine = new FHIRPathEngine(worker);
|
myFhirPathEngine = new FHIRPathEngine(worker);
|
||||||
myFhirPathEngine.setHostServices(new SearchParamExtractorR5HostServices());
|
myFhirPathEngine.setHostServices(new SearchParamExtractorR5HostServices());
|
||||||
}
|
}
|
||||||
|
@ -88,7 +85,7 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
private static class SearchParamExtractorR5HostServices implements FHIRPathEngine.IEvaluationContext {
|
private static class SearchParamExtractorR5HostServices implements FHIRPathEngine.IEvaluationContext {
|
||||||
|
|
||||||
private Map<String, Base> myResourceTypeToStub = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, Base> myResourceTypeToStub = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException {
|
public Base resolveConstant(Object appContext, String name, boolean beforeContext) throws PathEngineException {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.cross.IResourceLookup;
|
import ca.uhn.fhir.jpa.model.cross.IResourceLookup;
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||||
|
@ -119,8 +120,8 @@ public class SearchParamExtractorService {
|
||||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities = extractSearchParamQuantity(theResource);
|
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities = extractSearchParamQuantity(theResource);
|
||||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantities);
|
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantities);
|
||||||
theParams.myQuantityParams.addAll(quantities);
|
theParams.myQuantityParams.addAll(quantities);
|
||||||
|
|
||||||
if (myModelConfig.isNormalizedQuantityStorageSupported()|| myModelConfig.isNormalizedQuantitySearchSupported()) {
|
if (myModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED) || myModelConfig.getNormalizedQuantitySearchLevel().equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
|
||||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> quantitiesNormalized = extractSearchParamQuantityNormalized(theResource);
|
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> quantitiesNormalized = extractSearchParamQuantityNormalized(theResource);
|
||||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantitiesNormalized);
|
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantitiesNormalized);
|
||||||
theParams.myQuantityNormalizedParams.addAll(quantitiesNormalized);
|
theParams.myQuantityNormalizedParams.addAll(quantitiesNormalized);
|
||||||
|
|
|
@ -9,9 +9,6 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
|
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -23,7 +20,6 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
@ -43,9 +39,8 @@ public class IndexStressTest {
|
||||||
FhirContext ctx = FhirContext.forDstu3();
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
IValidationSupport mockValidationSupport = mock(IValidationSupport.class);
|
IValidationSupport mockValidationSupport = mock(IValidationSupport.class);
|
||||||
when(mockValidationSupport.getFhirContext()).thenReturn(ctx);
|
when(mockValidationSupport.getFhirContext()).thenReturn(ctx);
|
||||||
IValidationSupport validationSupport = new CachingValidationSupport(new ValidationSupportChain(new DefaultProfileValidationSupport(ctx), mockValidationSupport));
|
|
||||||
ISearchParamRegistry searchParamRegistry = mock(ISearchParamRegistry.class);
|
ISearchParamRegistry searchParamRegistry = mock(ISearchParamRegistry.class);
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ctx, validationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ctx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
|
|
||||||
Map<String, RuntimeSearchParam> spMap = ctx
|
Map<String, RuntimeSearchParam> spMap = ctx
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
|
@ -33,7 +32,6 @@ import org.hl7.fhir.dstu3.model.Observation;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
import org.hl7.fhir.dstu3.model.Questionnaire;
|
import org.hl7.fhir.dstu3.model.Questionnaire;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.text.Normalizer;
|
import java.text.Normalizer;
|
||||||
|
@ -51,8 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class SearchParamExtractorDstu3Test {
|
public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
private static FhirContext ourCtx = FhirContext.forCached(FhirVersionEnum.DSTU3);
|
||||||
private static IValidationSupport ourValidationSupport;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParamWithOrInPath() {
|
public void testParamWithOrInPath() {
|
||||||
|
@ -61,7 +58,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs);
|
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(obs);
|
||||||
assertEquals(1, tokens.size());
|
assertEquals(1, tokens.size());
|
||||||
|
@ -84,7 +81,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
Set<ResourceIndexedSearchParamString> params = extractor.extractSearchParamStrings(questionnaire);
|
Set<ResourceIndexedSearchParamString> params = extractor.extractSearchParamStrings(questionnaire);
|
||||||
assertEquals(1, params.size());
|
assertEquals(1, params.size());
|
||||||
|
@ -102,7 +99,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
Set<ResourceIndexedSearchParamNumber> params = extractor.extractSearchParamNumber(enc);
|
Set<ResourceIndexedSearchParamNumber> params = extractor.extractSearchParamNumber(enc);
|
||||||
assertEquals(1, params.size());
|
assertEquals(1, params.size());
|
||||||
|
@ -120,7 +117,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
Set<ResourceIndexedSearchParamNumber> params = extractor.extractSearchParamNumber(enc);
|
Set<ResourceIndexedSearchParamNumber> params = extractor.extractSearchParamNumber(enc);
|
||||||
assertEquals(1, params.size());
|
assertEquals(1, params.size());
|
||||||
|
@ -132,7 +129,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
public void testEmptyPath() {
|
public void testEmptyPath() {
|
||||||
|
|
||||||
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
|
|
||||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||||
|
@ -148,7 +145,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
public void testStringMissingResourceType() {
|
public void testStringMissingResourceType() {
|
||||||
|
|
||||||
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
|
|
||||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||||
|
@ -165,7 +162,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
public void testInvalidType() {
|
public void testInvalidType() {
|
||||||
|
|
||||||
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
MySearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -216,7 +213,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
ISearchParamRegistry searchParamRegistry = new MySearchParamRegistry();
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, ourValidationSupport, searchParamRegistry);
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||||
extractor.start();
|
extractor.start();
|
||||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> coords = extractor.extractSearchParamTokens(loc);
|
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> coords = extractor.extractSearchParamTokens(loc);
|
||||||
assertEquals(1, coords.size());
|
assertEquals(1, coords.size());
|
||||||
|
@ -227,7 +224,7 @@ public class SearchParamExtractorDstu3Test {
|
||||||
|
|
||||||
private static class MySearchParamRegistry implements ISearchParamRegistry {
|
private static class MySearchParamRegistry implements ISearchParamRegistry {
|
||||||
|
|
||||||
private List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>();
|
private final List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>();
|
||||||
|
|
||||||
public void addSearchParam(RuntimeSearchParam... theSearchParam) {
|
public void addSearchParam(RuntimeSearchParam... theSearchParam) {
|
||||||
myAddedSearchParams.clear();
|
myAddedSearchParams.clear();
|
||||||
|
@ -306,9 +303,4 @@ public class SearchParamExtractorDstu3Test {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() {
|
|
||||||
ourValidationSupport = new DefaultProfileValidationSupport(ourCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import ca.uhn.fhir.context.RuntimePrimitiveDatatypeXhtmlHl7OrgDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
@ -66,15 +65,15 @@ public class SearchParamExtractorMegaTest {
|
||||||
|
|
||||||
ctx = FhirContext.forDstu3();
|
ctx = FhirContext.forDstu3();
|
||||||
searchParamRegistry = new MySearchParamRegistry(ctx);
|
searchParamRegistry = new MySearchParamRegistry(ctx);
|
||||||
process(ctx, new SearchParamExtractorDstu3(new ModelConfig(), partitionSettings, ctx, new DefaultProfileValidationSupport(ctx), searchParamRegistry));
|
process(ctx, new SearchParamExtractorDstu3(new ModelConfig(), partitionSettings, ctx, searchParamRegistry));
|
||||||
|
|
||||||
ctx = FhirContext.forR4();
|
ctx = FhirContext.forR4();
|
||||||
searchParamRegistry = new MySearchParamRegistry(ctx);
|
searchParamRegistry = new MySearchParamRegistry(ctx);
|
||||||
process(ctx, new SearchParamExtractorR4(new ModelConfig(), partitionSettings, ctx, new DefaultProfileValidationSupport(ctx), searchParamRegistry));
|
process(ctx, new SearchParamExtractorR4(new ModelConfig(), partitionSettings, ctx, searchParamRegistry));
|
||||||
|
|
||||||
ctx = FhirContext.forR5();
|
ctx = FhirContext.forR5();
|
||||||
searchParamRegistry = new MySearchParamRegistry(ctx);
|
searchParamRegistry = new MySearchParamRegistry(ctx);
|
||||||
process(ctx, new SearchParamExtractorR5(new ModelConfig(), partitionSettings, ctx, new DefaultProfileValidationSupport(ctx), searchParamRegistry));
|
process(ctx, new SearchParamExtractorR5(new ModelConfig(), partitionSettings, ctx, searchParamRegistry));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process(FhirContext theCtx, BaseSearchParamExtractor theExtractor) throws Exception {
|
private void process(FhirContext theCtx, BaseSearchParamExtractor theExtractor) throws Exception {
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -1956,7 +1956,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
<version>0.8.5</version>
|
<version>0.8.6</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>ca/uhn/fhir/model/dstu2/**/*.class</exclude>
|
<exclude>ca/uhn/fhir/model/dstu2/**/*.class</exclude>
|
||||||
|
|
Loading…
Reference in New Issue