From eca21bec3ee248b7d40459f8389069030fe957dc Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 21 Jan 2020 14:30:51 -0500 Subject: [PATCH] exact coord matching works now --- .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 105 +++++++++++++++++- .../uhn/fhir/jpa/config/TestDstu3Config.java | 3 +- .../FhirResourceDaoDstu3SearchNoFtTest.java | 2 +- 3 files changed, 106 insertions(+), 4 deletions(-) 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 c57b4ac15b3..a4b0dbeb22d 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 @@ -66,6 +66,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseQuantityDt; +import ca.uhn.fhir.model.dstu2.resource.Location; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; @@ -467,6 +468,12 @@ public class SearchBuilder implements ISearchBuilder { String theParamName, List theList, SearchFilterParser.CompareOperation operation) { + + // FIXME KHS + if ("Location".equals(theResourceName) && Location.SP_NEAR_DISTANCE.equals(theParamName)) { + return null; + } + Join join = createJoin(JoinEnum.QUANTITY, theParamName); if (theList.get(0).getMissing() != null) { @@ -1288,6 +1295,43 @@ public class SearchBuilder implements ISearchBuilder { return outerPredicate; } + private Predicate addPredicateCoords(String theResourceName, + String theParamName, + List theList) { + return addPredicateCoords(theResourceName, + theParamName, + theList, + null); + } + + private Predicate addPredicateCoords(String theResourceName, + String theParamName, + List theList, + SearchFilterParser.CompareOperation operation) { + Join join = createJoin(JoinEnum.COORDS, theParamName); + + if (theList.get(0).getMissing() != null) { + addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join); + return null; + } + + List codePredicates = new ArrayList(); + for (IQueryParameterType nextOr : theList) { + + Predicate singleCode = createPredicateCoords(nextOr, + theResourceName, + theParamName, + myBuilder, + join, + operation); + codePredicates.add(singleCode); + } + + Predicate retVal = myBuilder.or(toArray(codePredicates)); + myPredicates.add(retVal); + return retVal; + } + private Predicate combineParamIndexPredicateWithParamNamePredicate(String theResourceName, String theParamName, From theFrom, Predicate thePredicate) { if (myDontUseHashesForSearch) { Predicate resourceTypePredicate = myBuilder.equal(theFrom.get("myResourceType"), theResourceName); @@ -1367,6 +1411,9 @@ public class SearchBuilder implements ISearchBuilder { case TOKEN: join = myResourceTableRoot.join("myParamsToken", JoinType.LEFT); break; + case COORDS: + join = myResourceTableRoot.join("myParamsCoords", JoinType.LEFT); + break; } JoinKey key = new JoinKey(theSearchParameterName, theType); @@ -2037,6 +2084,52 @@ public class SearchBuilder implements ISearchBuilder { return myBuilder.equal(theExpression, theCode); } + private Predicate createPredicateCoords(IQueryParameterType theParam, + String theResourceName, + String theParamName, + CriteriaBuilder theBuilder, + From theFrom, + SearchFilterParser.CompareOperation operation) { + // FIXME KHS + + String latitudeValue; + String longitudeValue; + BigDecimal valueValue; + + // FIXME KHS test + if (operation != null) { + throw new IllegalArgumentException("Operators not supported for Coordinate searches: " + operation.toString()); + } + + if (theParam instanceof TokenParam) { + TokenParam param = (TokenParam) theParam; + String value = param.getValue(); + String[] parts = value.split(":"); + // FIXME KHS test + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid position format '" + value + "'. Required format is 'latitude:longitude'"); + } + latitudeValue = parts[0]; + longitudeValue = parts[1]; + } else { + throw new IllegalArgumentException("Invalid position type: " + theParam.getClass()); + } + + Predicate latitude = null; + if (!isBlank(latitudeValue)) { + latitude = theBuilder.equal(theFrom.get("myLatitude"), latitudeValue); + } + + Predicate longitude = null; + if (!isBlank(longitudeValue)) { + longitude = theBuilder.equal(theFrom.get("myLongitude"), longitudeValue); + } + + Predicate singleCode = theBuilder.and(latitude, longitude); + + return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, singleCode); + } + @Override public Iterator createCountQuery(SearchParameterMap theParams, String theSearchUuid, RequestDetails theRequest) { myParams = theParams; @@ -2186,6 +2279,8 @@ public class SearchBuilder implements ISearchBuilder { */ final TypedQuery query = myEntityManager.createQuery(outerQuery); + // FIXME KHS query + if (theMaximumResults != null) { query.setMaxResults(theMaximumResults); } @@ -2197,6 +2292,7 @@ public class SearchBuilder implements ISearchBuilder { return createResourceLinkPathPredicate(myContext, theParamName, from, theResourceName); } + /** * @return Returns {@literal true} if any search parameter sorts were found, or false if * no sorts were found, or only non-search parameters ones (e.g. _id, _lastUpdated) @@ -2955,7 +3051,11 @@ public class SearchBuilder implements ISearchBuilder { break; case TOKEN: for (List nextAnd : theAndOrParams) { - addPredicateToken(theResourceName, theParamName, nextAnd); + if ("Location.position".equals(nextParamDef.getPath())) { + addPredicateCoords(theResourceName, theParamName, nextAnd); + } else { + addPredicateToken(theResourceName, theParamName, nextAnd); + } } break; case NUMBER: @@ -3129,7 +3229,8 @@ public class SearchBuilder implements ISearchBuilder { REFERENCE, STRING, TOKEN, - URI + URI, + COORDS } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu3Config.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu3Config.java index 87469cab62e..fb6b1a715b7 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu3Config.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu3Config.java @@ -83,7 +83,8 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 { }; retVal.setDriver(new org.h2.Driver()); - retVal.setUrl("jdbc:h2:mem:testdb_dstu3"); + // FIXME KHS + retVal.setUrl("jdbc:h2:file:./target/testdb_dstu3"); retVal.setMaxWaitMillis(10000); retVal.setUsername(""); retVal.setPassword(""); 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 193a2aa924c..771f75bbaf1 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 @@ -3474,7 +3474,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { double longitude = 2000.0; Location.LocationPositionComponent position = new Location.LocationPositionComponent().setLatitude(latitude).setLongitude(longitude); loc.setPosition(position); - IIdType locId = myLocationDao.create(loc).getId().toUnqualifiedVersionless(); + String locId = myLocationDao.create(loc).getId().toUnqualifiedVersionless().getValue(); SearchParameterMap map = new SearchParameterMap(); map.add(Location.SP_NEAR, new TokenParam(latitude + ":" + longitude));