From dcbdc83d8eb8a22c7d23b1a73cf54c927039bca5 Mon Sep 17 00:00:00 2001 From: Frank Tao Date: Fri, 11 Dec 2020 21:50:32 -0500 Subject: [PATCH 1/3] Supported composite sort --- .../jpa/search/builder/SearchBuilder.java | 51 ++++- .../dao/dstu2/FhirResourceDaoDstu2Test.java | 82 +++++++- .../dao/dstu3/FhirResourceDaoDstu3Test.java | 81 +++++++- .../jpa/dao/r4/FhirResourceDaoR4Test.java | 83 +++++++- .../provider/ResourceProviderDstu2Test.java | 100 +++++++-- .../dstu3/ResourceProviderDstu3Test.java | 93 +++++++-- .../provider/r4/ResourceProviderR4Test.java | 193 ++++++++++++++++-- 7 files changed, 597 insertions(+), 86 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java index b7d748d03a0..2fed771bc31 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java @@ -444,7 +444,7 @@ public class SearchBuilder implements ISearchBuilder { if (generatedSql.isMatchNothing()) { return Optional.empty(); } - + SearchQueryExecutor executor = mySqlBuilderFactory.newSearchQueryExecutor(generatedSql, myMaxResultsToFetch); return Optional.of(executor); } @@ -528,9 +528,25 @@ public class SearchBuilder implements ISearchBuilder { break; case QUANTITY: theQueryStack.addSortOnQuantity(myResourceName, theSort.getParamName(), ascending); + break; + case COMPOSITE: + List theCompositList = param.getCompositeOf(); + if (theCompositList == null) { + throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + " is not defined by the resource " + myResourceName); + } + if (theCompositList.size() != 2) { + throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + + " must have 2 composite types declared in parameter annotation, found " + + theCompositList.size()); + } + RuntimeSearchParam left = theCompositList.get(0); + RuntimeSearchParam right = theCompositList.get(1); + + createCompositeSort(theQueryStack, myResourceName, left.getParamType(), left.getName(), ascending); + createCompositeSort(theQueryStack, myResourceName, right.getParamType(), right.getName(), ascending); + break; case SPECIAL: - case COMPOSITE: case HAS: default: throw new InvalidRequestException("This server does not support _sort specifications of type " + param.getParamType() + " - Can't serve _sort=" + theSort.getParamName()); @@ -542,6 +558,37 @@ public class SearchBuilder implements ISearchBuilder { createSort(theQueryStack, theSort.getChain()); } + + private void createCompositeSort(QueryStack theQueryStack, String theResourceName, RestSearchParameterTypeEnum theParamType, String theParamName, boolean theAscending) { + + switch (theParamType) { + case STRING: + theQueryStack.addSortOnString(myResourceName, theParamName, theAscending); + break; + case DATE: + theQueryStack.addSortOnDate(myResourceName, theParamName, theAscending); + break; + case REFERENCE: + theQueryStack.addSortOnResourceLink(myResourceName, theParamName, theAscending); + break; + case TOKEN: + theQueryStack.addSortOnToken(myResourceName, theParamName, theAscending); + break; + case NUMBER: + theQueryStack.addSortOnNumber(myResourceName, theParamName, theAscending); + break; + case URI: + theQueryStack.addSortOnUri(myResourceName, theParamName, theAscending); + break; + case QUANTITY: + theQueryStack.addSortOnQuantity(myResourceName, theParamName, theAscending); + break; + default: + throw new InvalidRequestException("This server does not support _sort specifications of type " + + theParamType + " - Can't serve _sort=" + theParamName); + } + + } private void doLoadPids(Collection thePids, Collection theIncludedPids, List theResourceListToPopulate, boolean theForHistoryOperation, Map thePosition) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java index 4b81537515e..339c23e6d91 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java @@ -2063,20 +2063,80 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test { @Test() public void testSortByComposite() { - Observation o = new Observation(); - o.getCode().setText("testSortByComposite"); - myObservationDao.create(o, mySrd); + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().addFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringDt("200")); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringDt("300")); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringDt("150")); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringDt("250")); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + SearchParameterMap pm = new SearchParameterMap(); - pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT)); - try { - myObservationDao.search(pm).size(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-concept", e.getMessage()); - } + pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_STRING)); + + + IBundleProvider found = myObservationDao.search(pm); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, list.size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } - @Test public void testSortByDate() { Patient p = new Patient(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java index 9b707a9ea7b..e69a5d91b55 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java @@ -30,6 +30,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; + import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; @@ -2551,18 +2552,78 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test { @Test() public void testSortByComposite() { - Observation o = new Observation(); - o.getCode().setText("testSortByComposite"); - myObservationDao.create(o, mySrd); + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("200")); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("300")); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("150")); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("250")); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + SearchParameterMap pm = new SearchParameterMap(); - pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT)); - try { - myObservationDao.search(pm).size(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-concept", e.getMessage()); - } + pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_STRING)); + + IBundleProvider found = myObservationDao.search(pm); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, list.size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } @Test diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java index 2ad87ecf103..82cc8a2d059 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java @@ -2979,21 +2979,82 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test { assertTrue(next.getResource().getIdElement().hasIdPart()); } } - + @Test() public void testSortByComposite() { - Observation o = new Observation(); - o.getCode().setText("testSortByComposite"); - myObservationDao.create(o, mySrd); + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("200")); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("300")); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("150")); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new StringType("250")); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + SearchParameterMap pm = new SearchParameterMap(); - pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT)); - try { - myObservationDao.search(pm).size(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-concept", e.getMessage()); - } + pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_STRING)); + + + IBundleProvider found = myObservationDao.search(pm); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, list.size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } @Test diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index c4a34b2d102..bcf63a55729 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -35,12 +35,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.model.dstu2.resource.SearchParameter; import ca.uhn.fhir.model.dstu2.valueset.XPathUsageTypeEnum; import ca.uhn.fhir.model.primitive.IntegerDt; -import ca.uhn.fhir.rest.api.SearchTotalModeEnum; -import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.gclient.NumberClientParam; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -53,11 +50,9 @@ import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; -import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -74,6 +69,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.PeriodDt; +import ca.uhn.fhir.model.dstu2.composite.QuantityDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.resource.BaseResource; import ca.uhn.fhir.model.dstu2.resource.Basic; @@ -131,7 +127,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.util.StopWatch; -import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { @@ -2185,23 +2180,86 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { } @Test - public void testSearchWithInvalidSort() { - try { - Observation o = new Observation(); - o.getCode().setText("testSearchWithInvalidSort"); - myObservationDao.create(o, mySrd); - IBaseBundle bundle = ourClient - .search() - .forResource(Observation.class) - .sort().ascending(Observation.CODE_VALUE_QUANTITY) // composite sort not supported yet - .prettyPrint() - .execute(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("HTTP 400 Bad Request: This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-quantity", e.getMessage()); + public void testSearchWithCompositeSortWith_CodeValueQuantity() throws IOException { + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().addFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new QuantityDt().setValue(200)); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new QuantityDt().setValue(300)); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new QuantityDt().setValue(150)); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReference(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new QuantityDt().setValue(250)); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + String uri = ourServerBase + "/Observation?_sort=code-value-quantity"; + Bundle found; + + HttpGet get = new HttpGet(uri); + try (CloseableHttpResponse resp = ourHttpClient.execute(get)) { + String output = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + found = myFhirCtx.newXmlParser().parseResource(Bundle.class, output); + } + + ourLog.info("Bundle: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(found)); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, found.getEntry().size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } - + @Test public void testSearchWithMissing() { ourLog.info("Starting testSearchWithMissing"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 5c000b1e89a..c5054bf7ffa 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -3412,24 +3412,87 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { } @Test - public void testSearchWithInvalidSort() { - try { - Observation o = new Observation(); - o.getCode().setText("testSearchWithInvalidSort"); - myObservationDao.create(o, mySrd); - ourClient - .search() - .forResource(Observation.class) - .sort().ascending(Observation.CODE_VALUE_QUANTITY) // composite sort not supported yet - .prettyPrint() - .returnBundle(Bundle.class) - .execute(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("HTTP 400 Bad Request: This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-quantity", e.getMessage()); + public void testSearchWithCompositeSort_CodeValueDate() throws IOException { + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new DateTimeType("2020-02-01")); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new DateTimeType("2020-04-01")); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new DateTimeType("2020-01-01")); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new DateTimeType("2020-03-01")); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + String uri = ourServerBase + "/Observation?_sort=code-value-date"; + Bundle found; + + HttpGet get = new HttpGet(uri); + try (CloseableHttpResponse resp = ourHttpClient.execute(get)) { + String output = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + found = myFhirCtx.newXmlParser().parseResource(Bundle.class, output); + } + + ourLog.info("Bundle: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(found)); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, found.getEntry().size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } + @Test public void testSearchWithMissing() { ourLog.info("Starting testSearchWithMissing"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index 15d6533f1f3..cc344111f56 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -75,6 +75,7 @@ import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; import org.hl7.fhir.r4.model.CarePlan; import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeType; +import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Condition; import org.hl7.fhir.r4.model.DateTimeType; @@ -104,6 +105,7 @@ import org.hl7.fhir.r4.model.MolecularSequence; import org.hl7.fhir.r4.model.Narrative; import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Observation.ObservationComponentComponent; import org.hl7.fhir.r4.model.Observation.ObservationStatus; import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Organization; @@ -4546,24 +4548,183 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } @Test - public void testSearchWithInvalidSort() { - try { - Observation o = new Observation(); - o.getCode().setText("testSearchWithInvalidSort"); - myObservationDao.create(o, mySrd); - myClient - .search() - .forResource(Observation.class) - .sort().ascending(Observation.CODE_VALUE_QUANTITY) // composite sort not supported yet - .prettyPrint() - .returnBundle(Bundle.class) - .execute(); - fail(); - } catch (InvalidRequestException e) { - assertEquals("HTTP 400 Bad Request: This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-quantity", e.getMessage()); + public void testSearchWithCompositeSortWith_CodeValueQuantity() throws IOException { + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new Quantity().setValue(200)); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new Quantity().setValue(300)); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new Quantity().setValue(150)); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + obs.getCode().addCoding().setCode("2345-7").setSystem("http://loinc.org"); + obs.setValue(new Quantity().setValue(250)); + + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + String uri = ourServerBase + "/Observation?_sort=code-value-quantity"; + Bundle found; + + HttpGet get = new HttpGet(uri); + try (CloseableHttpResponse resp = ourHttpClient.execute(get)) { + String output = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + found = myFhirCtx.newXmlParser().parseResource(Bundle.class, output); + } + + ourLog.info("Bundle: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(found)); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, found.getEntry().size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); } - + + @Test + public void testSearchWithCompositeSortWith_CompCodeValueQuantity() throws IOException { + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(200)); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(300)); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(150)); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(250)); + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + String uri = ourServerBase + "/Observation?_sort=combo-code-value-quantity"; + Bundle found; + + HttpGet get = new HttpGet(uri); + try (CloseableHttpResponse resp = ourHttpClient.execute(get)) { + String output = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + found = myFhirCtx.newXmlParser().parseResource(Bundle.class, output); + } + + ourLog.info("Bundle: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(found)); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, found.getEntry().size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); + } + + @Test public void testSearchWithMissing() { myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED); From 0411967e26add7dd1c6a2feae4f03b6742e9abfc Mon Sep 17 00:00:00 2001 From: Frank Tao Date: Fri, 11 Dec 2020 22:25:12 -0500 Subject: [PATCH 2/3] Added composite sort test case for R5 --- .../provider/r5/ResourceProviderR5Test.java | 144 ++++++++++++++++-- 1 file changed, 128 insertions(+), 16 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java index d91fba41fde..ac1a6676c56 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java @@ -1,13 +1,16 @@ package ca.uhn.fhir.jpa.provider.r5; -import ca.uhn.fhir.jpa.api.config.DaoConfig; -import ca.uhn.fhir.jpa.entity.Search; -import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; -import ca.uhn.fhir.parser.StrictErrorHandler; -import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor; -import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; -import ca.uhn.fhir.util.UrlUtil; -import com.google.common.base.Charsets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; @@ -16,24 +19,29 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r5.model.Bundle; +import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.IdType; import org.hl7.fhir.r5.model.Observation; +import org.hl7.fhir.r5.model.Observation.ObservationComponentComponent; import org.hl7.fhir.r5.model.Patient; +import org.hl7.fhir.r5.model.Quantity; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; +import com.google.common.base.Charsets; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.hamcrest.MatcherAssert.assertThat; +import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.entity.Search; +import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor; +import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; +import ca.uhn.fhir.util.UrlUtil; @SuppressWarnings("Duplicates") public class ResourceProviderR5Test extends BaseResourceProviderR5Test { @@ -246,5 +254,109 @@ public class ResourceProviderR5Test extends BaseResourceProviderR5Test { assertEquals(0, output.getEntry().size()); } + @Test + public void testSearchWithCompositeSort() throws IOException { + + IIdType pid0; + IIdType oid1; + IIdType oid2; + IIdType oid3; + IIdType oid4; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(200)); + + oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(300)); + + oid2 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(150)); + + oid3 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + { + Observation obs = new Observation(); + obs.addIdentifier().setSystem("urn:system").setValue("FOO"); + obs.getSubject().setReferenceElement(pid0); + + ObservationComponentComponent comp = obs.addComponent(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setCode("2345-7").setSystem("http://loinc.org"); + comp.setCode(cc); + comp.setValue(new Quantity().setValue(250)); + oid4 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless(); + + ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs)); + } + + String uri = ourServerBase + "/Observation?_sort=combo-code-value-quantity"; + Bundle found; + + HttpGet get = new HttpGet(uri); + try (CloseableHttpResponse resp = ourHttpClient.execute(get)) { + String output = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + found = myFhirCtx.newXmlParser().parseResource(Bundle.class, output); + } + + ourLog.info("Bundle: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(found)); + + List list = toUnqualifiedVersionlessIds(found); + assertEquals(4, found.getEntry().size()); + assertEquals(oid3, list.get(0)); + assertEquals(oid1, list.get(1)); + assertEquals(oid4, list.get(2)); + assertEquals(oid2, list.get(3)); + } + protected List toUnqualifiedVersionlessIds(Bundle theFound) { + List retVal = new ArrayList<>(); + for (BundleEntryComponent next : theFound.getEntry()) { + if (next.getResource()!= null) { + retVal.add(next.getResource().getIdElement().toUnqualifiedVersionless()); + } + } + return retVal; + } } From de845300c2910d3bc577744b084fd6d97b171c9f Mon Sep 17 00:00:00 2001 From: Frank Tao Date: Wed, 16 Dec 2020 15:48:10 -0500 Subject: [PATCH 3/3] Updated based on the review comments --- .../jpa/search/builder/SearchBuilder.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java index 2fed771bc31..ba0e88d3715 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java @@ -530,17 +530,17 @@ public class SearchBuilder implements ISearchBuilder { theQueryStack.addSortOnQuantity(myResourceName, theSort.getParamName(), ascending); break; case COMPOSITE: - List theCompositList = param.getCompositeOf(); - if (theCompositList == null) { + List compositList = param.getCompositeOf(); + if (compositList == null) { throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + " is not defined by the resource " + myResourceName); } - if (theCompositList.size() != 2) { + if (compositList.size() != 2) { throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + " must have 2 composite types declared in parameter annotation, found " - + theCompositList.size()); + + compositList.size()); } - RuntimeSearchParam left = theCompositList.get(0); - RuntimeSearchParam right = theCompositList.get(1); + RuntimeSearchParam left = compositList.get(0); + RuntimeSearchParam right = compositList.get(1); createCompositeSort(theQueryStack, myResourceName, left.getParamType(), left.getName(), ascending); createCompositeSort(theQueryStack, myResourceName, right.getParamType(), right.getName(), ascending); @@ -568,24 +568,14 @@ public class SearchBuilder implements ISearchBuilder { case DATE: theQueryStack.addSortOnDate(myResourceName, theParamName, theAscending); break; - case REFERENCE: - theQueryStack.addSortOnResourceLink(myResourceName, theParamName, theAscending); - break; case TOKEN: theQueryStack.addSortOnToken(myResourceName, theParamName, theAscending); break; - case NUMBER: - theQueryStack.addSortOnNumber(myResourceName, theParamName, theAscending); - break; - case URI: - theQueryStack.addSortOnUri(myResourceName, theParamName, theAscending); - break; case QUANTITY: theQueryStack.addSortOnQuantity(myResourceName, theParamName, theAscending); break; default: - throw new InvalidRequestException("This server does not support _sort specifications of type " - + theParamType + " - Can't serve _sort=" + theParamName); + throw new InvalidRequestException("Don't know how to handle composite parameter with type of " + theParamType + " on _sort="+ theParamName); } }