diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index a4b0dbeb22d..b5f0b180829 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -2770,6 +2770,8 @@ public class SearchBuilder implements ISearchBuilder { myParams.isAllParametersHaveNoModifier(); if (couldBeEligibleForCompositeUniqueSpProcessing) { + // FIXME KHS method + // Since we're going to remove elements below theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList)); @@ -2846,7 +2848,6 @@ public class SearchBuilder implements ISearchBuilder { } - private void ensureSubListsAreWritable(List> theListOfLists) { for (int i = 0; i < theListOfLists.size(); i++) { List oldSubList = theListOfLists.get(i); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java index 8dcbda74c4e..6e4c4861173 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java @@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.dstu3; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.model.entity.*; +import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.SearchParamConstants; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum; @@ -35,6 +36,7 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; @@ -56,6 +58,9 @@ import static org.mockito.Mockito.mock; public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3SearchNoFtTest.class); + @Autowired + MatchUrlService myMatchUrlService; + @Before public void beforeDisableResultReuse() { myDaoConfig.setReuseCachedSearchResultsForMillis(null); @@ -3494,10 +3499,17 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { loc.setPosition(position); String locId = myLocationDao.create(loc).getId().toUnqualifiedVersionless().getValue(); - SearchParameterMap map = new SearchParameterMap(); - map.add(Location.SP_NEAR, new TokenParam((latitude + offset) + ":" + (longitude - offset))); - QuantityParam distance = new QuantityParam(ParamPrefixEnum.LESSTHAN_OR_EQUALS, offset * 2, "http://unitsofmeasure.org", "km"); - map.add(Location.SP_NEAR_DISTANCE, distance); + SearchParameterMap map = myMatchUrlService.translateMatchUrl( + "Location?" + + Location.SP_NEAR + "=" + (latitude + offset) + ":" + (longitude - offset) + + "&" + + Location.SP_NEAR_DISTANCE + "=" + (offset * 2) + "|http://unitsofmeasure.org|km", myFhirCtx.getResourceDefinition("Location")); + + // FIXME KHS +// new SearchParameterMap(); +// map.add(Location.SP_NEAR, new TokenParam()); +// QuantityParam distance = new QuantityParam(ParamPrefixEnum.LESSTHAN_OR_EQUALS, ); +// map.add(Location.SP_NEAR_DISTANCE, distance); List ids = toUnqualifiedVersionlessIdValues(myLocationDao.search(map)); assertThat(ids, contains(locId)); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java index 803c47e11e6..f324a0541a8 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java @@ -2,12 +2,16 @@ package ca.uhn.fhir.jpa.searchparam; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.RuntimeResourceDefinition; +import ca.uhn.fhir.jpa.config.TestDstu3Config; import ca.uhn.fhir.jpa.config.TestR4Config; import ca.uhn.fhir.jpa.dao.BaseJpaTest; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; -import ca.uhn.fhir.model.dstu2.resource.Condition; +import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.util.TestUtil; +import org.hl7.fhir.dstu3.model.Condition; +import org.hl7.fhir.dstu3.model.Location; +import org.hl7.fhir.dstu3.model.Quantity; import org.junit.AfterClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,16 +21,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.PlatformTransactionManager; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {TestR4Config.class}) +@ContextConfiguration(classes = {TestDstu3Config.class}) public class MatchUrlServiceTest extends BaseJpaTest { - private static FhirContext ourCtx = FhirContext.forDstu2(); + private static FhirContext ourCtx = FhirContext.forDstu3(); @Autowired MatchUrlService myMatchUrlService; @@ -47,6 +52,21 @@ public class MatchUrlServiceTest extends BaseJpaTest { assertEquals("304", ((ReferenceParam)match.get("patient").get(0).get(0)).getIdPart()); } + @Test + public void testPullOutNearDistance() { + Double kmDistance = 123.4; + + SearchParameterMap map = myMatchUrlService.translateMatchUrl( + "Location?" + + Location.SP_NEAR + "=1000.0:2000.0" + + "&" + + Location.SP_NEAR_DISTANCE + "=" + kmDistance + "|http://unitsofmeasure.org|km", ourCtx.getResourceDefinition("Location")); + + QuantityParam nearDistanceParam = map.getNearDistanceParam(); + assertNotNull(nearDistanceParam); + // FIXME KHS assert + } + @Override protected FhirContext getContext() { return ourCtx; diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java index fb77ea8af24..1717539e9cc 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java @@ -26,11 +26,14 @@ import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterType; +import ca.uhn.fhir.model.dstu2.resource.Location; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.QualifiedParamList; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.ParameterUtil; +import ca.uhn.fhir.rest.param.QuantityAndListParam; +import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.UrlUtil; @@ -113,6 +116,10 @@ public class MatchUrlService { } else if (Constants.PARAM_SOURCE.equals(nextParamName)) { IQueryParameterAnd param = ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList); paramMap.add(nextParamName, param); + } else if (Location.SP_NEAR_DISTANCE.equals(nextParamName)) { + QuantityAndListParam nearDistanceAndListParam = (QuantityAndListParam) ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.QUANTITY, nextParamName, paramList); + // FIXME KHS + paramMap.setNearDistanceParam(nearDistanceAndListParam); } else if (nextParamName.startsWith("_")) { // ignore these since they aren't search params (e.g. _sort) } else { diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java index 916711eecbb..316a42415e0 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java @@ -6,9 +6,7 @@ import ca.uhn.fhir.model.api.IQueryParameterOr; import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.api.*; -import ca.uhn.fhir.rest.param.DateParam; -import ca.uhn.fhir.rest.param.DateRangeParam; -import ca.uhn.fhir.rest.param.QuantityParam; +import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.util.ObjectUtil; import ca.uhn.fhir.util.UrlUtil; import org.apache.commons.lang3.StringUtils; @@ -59,6 +57,7 @@ public class SearchParameterMap implements Serializable { private SortSpec mySort; private SummaryEnum mySummaryMode; private SearchTotalModeEnum mySearchTotalMode; + private QuantityParam myNearDistanceParam; /** * Constructor @@ -495,6 +494,25 @@ public class SearchParameterMap implements Serializable { } } + public void setNearDistanceParam(QuantityAndListParam theQuantityAndListParam) { + List orTokens = theQuantityAndListParam.getValuesAsQueryTokens(); + if (orTokens.isEmpty()) { + return; + } + // FIXME KHS error if size > 0 + QuantityOrListParam quantityOrListParam = orTokens.get(0); + List tokens = quantityOrListParam.getValuesAsQueryTokens(); + if (tokens.isEmpty()) { + return; + } + // FIXME KHS error if size > 0 + myNearDistanceParam = tokens.get(0); + } + + public QuantityParam getNearDistanceParam() { + return myNearDistanceParam; + } + public enum EverythingModeEnum { /* * Don't reorder! We rely on the ordinals