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 680b64e056c..daf99217c59 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 @@ -46,6 +46,7 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.CollectionUtils; import org.springframework.web.servlet.ThemeResolver; import com.google.common.collect.Lists; @@ -100,7 +101,7 @@ public class SearchBuilder { private Root myResourceTableRoot; private ArrayList myPredicates; private CriteriaBuilder myBuilder; - private CriteriaQuery myResourceTableQuery; + private AbstractQuery myResourceTableQuery; private PlatformTransactionManager myPlatformTransactionManager; public SearchBuilder(FhirContext theFhirContext, EntityManager theEntityManager, PlatformTransactionManager thePlatformTransactionManager, IFulltextSearchSvc theFulltextSearchSvc, @@ -1257,19 +1258,20 @@ public class SearchBuilder { throw new InvalidRequestException("This server does not support _sort specifications of type " + param.getParamType() + " - Can't serve _sort=" + theSort.getParamName()); } - From stringJoin = theFrom.join(joinAttrName, JoinType.INNER); + From join = theFrom.join(joinAttrName, JoinType.LEFT); if (param.getParamType() == RestSearchParameterTypeEnum.REFERENCE) { - thePredicates.add(stringJoin.get("mySourcePath").as(String.class).in(param.getPathsSplit())); + thePredicates.add(join.get("mySourcePath").as(String.class).in(param.getPathsSplit())); } else { - thePredicates.add(theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName())); + Predicate joinParam1 = theBuilder.equal(join.get("myParamName"), theSort.getParamName()); + thePredicates.add(joinParam1); } for (String next : sortAttrName) { if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) { - theOrders.add(theBuilder.asc(stringJoin.get(next))); + theOrders.add(theBuilder.asc(join.get(next))); } else { - theOrders.add(theBuilder.desc(stringJoin.get(next))); + theOrders.add(theBuilder.desc(join.get(next))); } } @@ -1470,27 +1472,53 @@ public class SearchBuilder { public List loadSearchPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) { - // if (myFulltextSearchSvc == null) { - // if (theParams.containsKey(Constants.PARAM_TEXT)) { - // throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT); - // } else if (theParams.containsKey(Constants.PARAM_CONTENT)) { - // throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT); - // } - // } else { - // // FIXME: add from and to - // List searchResultPids = myFulltextSearchSvc.search(myResourceName, theParams); - // if (searchResultPids != null) { - // if (searchResultPids.isEmpty()) { - // return Collections.emptyList(); - // } - // return searchResultPids; - // } - // } - myBuilder = myEntityManager.getCriteriaBuilder(); - myResourceTableQuery = myBuilder.createTupleQuery(); + CriteriaQuery outerQuery = null; + + /* + * Sort + * + * If we have a sort, we wrap the criteria search (the search that actually + * finds the appropriate resources) in an outer search which is then sorted + */ + if (theParams.getSort() != null) { + + outerQuery = myBuilder.createQuery(Long.class); + Root outerQueryFrom = outerQuery.from(ResourceTable.class); + + List orders = Lists.newArrayList(); + List predicates = Lists.newArrayList(); + + createSort(myBuilder, outerQueryFrom, theParams.getSort(), orders, predicates); + if (orders.size() > 0) { + outerQuery.orderBy(orders); + } + + Subquery subQ = outerQuery.subquery(Long.class); + Root subQfrom = subQ.from(ResourceTable.class); + + myResourceTableQuery = subQ; + myResourceTableRoot = subQfrom; + + Expression selectExpr = subQfrom.get("myId").as(Long.class); + subQ.select(selectExpr); + + predicates.add(0, myBuilder.in(outerQueryFrom.get("myId").as(Long.class)).value(subQ)); + + outerQuery.multiselect(outerQueryFrom.get("myId").as(Long.class)); + outerQuery.where(predicates.toArray(new Predicate[0])); + + } else { + + outerQuery = myBuilder.createQuery(Long.class); + myResourceTableQuery = outerQuery; + myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class); + outerQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class)); + + } + + myResourceTableQuery.distinct(true); - myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class); myPredicates = new ArrayList(); if (theParams.getEverythingMode() == null) { myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), myResourceName)); @@ -1509,7 +1537,9 @@ public class SearchBuilder { Long pid = BaseHapiFhirDao.translateForcedIdToPid(myResourceName, idParm.getValue(), myForcedIdDao); myPredicates.add(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid)); } else { - myPredicates.add(myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName)); + Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName); + Predicate sourceTypePredicate = myBuilder.equal(myResourceTableRoot.get("myResourceType").as(String.class), myResourceName); + myPredicates.add(myBuilder.or(sourceTypePredicate, targetTypePredicate)); } } else { @@ -1539,14 +1569,19 @@ public class SearchBuilder { myResourceTableQuery.where(myBuilder.and(SearchBuilder.toArray(myPredicates))); - myResourceTableQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class)); - TypedQuery query = myEntityManager.createQuery(myResourceTableQuery); + /* + * Now perform the search + */ + TypedQuery query = myEntityManager.createQuery(outerQuery); query.setFirstResult(theFromIndex); query.setMaxResults(theToIndex - theFromIndex); List pids = new ArrayList(); - for (Tuple next : query.getResultList()) { - pids.add(next.get(0, Long.class)); + + for (Long next : query.getResultList()) { + if (next != null) { + pids.add(next); + } } return pids; @@ -1889,6 +1924,10 @@ public class SearchBuilder { return; } + // Dupes will cause a crash later anyhow, but this is expensive so only do it + // when running asserts + assert new HashSet(theIncludePids).size() == theIncludePids.size() : "PID list contains duplicates: " + theIncludePids; + Map position = new HashMap(); for (Long next : theIncludePids) { position.put(next, theResourceListToPopulate.size()); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java index ef36ac6bd24..4a7cccd2558 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java @@ -77,11 +77,11 @@ public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc { entitiesToSave.add(present); } - mySearchParamPresentDao.deleteInBatch(entitiesToDelete); - mySearchParamPresentDao.save(entitiesToSave); - } + mySearchParamPresentDao.deleteInBatch(entitiesToDelete); + mySearchParamPresentDao.save(entitiesToSave); + } @Override diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java index fc57677dbbf..400f59242dc 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java @@ -32,6 +32,7 @@ import org.springframework.transaction.support.TransactionTemplate; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test; +import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; @@ -190,7 +191,7 @@ public abstract class BaseJpaTest { return bundleStr; } - public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager) { + public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager, ISearchParamPresenceSvc theSearchParamPresenceSvc) { TransactionTemplate txTemplate = new TransactionTemplate(theTxManager); txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED); txTemplate.execute(new TransactionCallback() { @@ -255,6 +256,7 @@ public abstract class BaseJpaTest { return null; } }); + theSearchParamPresenceSvc.flushCachesForUnitTest(); } public static Set toCodes(Set theConcepts) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java index efa516ad851..abe68c1d281 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java @@ -26,12 +26,14 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.transaction.PlatformTransactionManager; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.config.TestDstu1Config; import ca.uhn.fhir.jpa.entity.TagTypeEnum; +import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.IResource; @@ -61,10 +63,11 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest { private static IFhirResourceDao ourPatientDao; private static IFhirSystemDao, MetaDt> ourSystemDao; private static PlatformTransactionManager ourTxManager; + private static ISearchParamPresenceSvc ourSearchParamPresenceSvc; @Before public void before() { - super.purgeDatabase(ourEntityManager, ourTxManager); + super.purgeDatabase(ourEntityManager, ourTxManager, ourSearchParamPresenceSvc); } @Override @@ -493,6 +496,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest { ourSystemDao = ourCtx.getBean("mySystemDaoDstu1", IFhirSystemDao.class); ourEntityManager = ourCtx.getBean(EntityManager.class); ourTxManager = ourCtx.getBean(PlatformTransactionManager.class); + ourSearchParamPresenceSvc = ourCtx.getBean(ISearchParamPresenceSvc.class); } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java index d3fb9476e33..ba2a3bf5ff2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java @@ -37,6 +37,7 @@ import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.entity.ResourceTable; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; +import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt; @@ -147,6 +148,9 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest { @Autowired @Qualifier("myValueSetDaoDstu2") protected IFhirResourceDaoValueSet myValueSetDao; + @Autowired + protected ISearchParamPresenceSvc mySearchParamPresenceSvc; + @Before public void beforeCreateInterceptor() { myInterceptor = mock(IServerInterceptor.class); @@ -167,7 +171,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest { @Transactional() public void beforePurgeDatabase() { final EntityManager entityManager = this.myEntityManager; - purgeDatabase(entityManager, myTxManager); + purgeDatabase(entityManager, myTxManager, mySearchParamPresenceSvc); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java index 6122a1fbfa6..6622fbaf352 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java @@ -1306,16 +1306,16 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test { } SearchParameterMap params; + + params = new SearchParameterMap(); + params.add(Patient.SP_ORGANIZATION, new ReferenceParam().setMissing(true)); + assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(pid1, pid3)); params = new SearchParameterMap(); params.add(Patient.SP_NAME, new StringParam("FAMILY1")); params.add(Patient.SP_ORGANIZATION, new ReferenceParam().setMissing(true)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(pid1)); - params = new SearchParameterMap(); - params.add(Patient.SP_ORGANIZATION, new ReferenceParam().setMissing(true)); - assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(pid1, pid3)); - params = new SearchParameterMap(); params.add(Patient.SP_NAME, new StringParam("FAMILY9999")); params.add(Patient.SP_ORGANIZATION, new ReferenceParam().setMissing(true)); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java index 155653ba7ee..394f95654be 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java @@ -224,8 +224,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest { @Transactional() public void beforePurgeDatabase() { final EntityManager entityManager = this.myEntityManager; - purgeDatabase(entityManager, myTxManager); - mySearchParamPresenceSvc.flushCachesForUnitTest(); + purgeDatabase(entityManager, myTxManager, mySearchParamPresenceSvc); } @Before 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 932dd459f94..1fa318a3841 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 @@ -108,7 +108,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { @Test public void testEverythingTimings() throws Exception { - String methodName = "testEverythingIncludesBackReferences"; + String methodName = "testEverythingTimings"; Organization org = new Organization(); org.setName(methodName); @@ -124,7 +124,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless(); Patient pat2 = new Patient(); - pat2.addAddress().addLine(methodName); + pat2.addAddress().addLine(methodName + "2"); pat2.getManagingOrganization().setReferenceElement(orgId); IIdType patId2 = myPatientDao.create(pat2, mySrd).getId().toUnqualifiedVersionless(); @@ -2862,6 +2862,125 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test { } + @Test + public void testSortOnPopulatedField() throws Exception { + Patient pBA = new Patient(); + pBA.setId("BA"); + pBA.setActive(true); + pBA.setGender(AdministrativeGender.MALE); + pBA.addName().setFamily("B").addGiven("A"); + myPatientDao.update(pBA); + + Patient pBB = new Patient(); + pBB.setId("BB"); + pBB.setActive(true); + pBB.setGender(AdministrativeGender.MALE); + pBB.addName().setFamily("B").addGiven("B"); + pBB.addName().setFamily("Z").addGiven("Z"); + myPatientDao.update(pBB); + + Patient pAB = new Patient(); + pAB.setId("AB"); + pAB.setActive(true); + pAB.setGender(AdministrativeGender.MALE); + pAB.addName().setFamily("A").addGiven("B"); + myPatientDao.update(pAB); + + Patient pAA = new Patient(); + pAA.setId("AA"); + pAA.setActive(true); + pAA.setGender(AdministrativeGender.MALE); + pAA.addName().setFamily("A").addGiven("A"); + myPatientDao.update(pAA); + + SearchParameterMap map; + List ids; + + map = new SearchParameterMap(); + map.setSort(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB")); + + map = new SearchParameterMap(); + map.setSort(new SortSpec("gender").setChain(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC)))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + ourLog.info("IDS: {}", ids); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB")); + + map = new SearchParameterMap(); + map.add(Patient.SP_ACTIVE, new TokenParam(null, "true")); + map.setSort(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB")); + } + + @Test + public void testSort() throws Exception { + Patient pBA = new Patient(); + pBA.setId("BA"); + pBA.setActive(true); + pBA.setGender(AdministrativeGender.MALE); + pBA.addName().setFamily("B").addGiven("A"); + myPatientDao.update(pBA); + + Patient pBB = new Patient(); + pBB.setId("BB"); + pBB.setActive(true); + pBB.setGender(AdministrativeGender.MALE); + pBB.addName().setFamily("B").addGiven("B"); + myPatientDao.update(pBB); + + Patient pAB = new Patient(); + pAB.setId("AB"); + pAB.setActive(true); + pAB.setGender(AdministrativeGender.MALE); + pAB.addName().setFamily("A").addGiven("B"); + myPatientDao.update(pAB); + + Patient pAA = new Patient(); + pAA.setId("AA"); + pAA.setActive(true); + pAA.setGender(AdministrativeGender.MALE); + pAA.addName().setFamily("A").addGiven("A"); + myPatientDao.update(pAA); + + Patient pCA = new Patient(); + pCA.setId("CA"); + pCA.setActive(false); + pCA.addName().setFamily("C").addGiven("A"); + pCA.addName().setFamily("Z").addGiven("A"); + myPatientDao.update(pCA); + + SearchParameterMap map; + List ids; + + // Sort across all resources + map = new SearchParameterMap(); + map.setSort(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB", "Patient/CA")); + + // A sort on a field that isn't populated in all cases + map = new SearchParameterMap(); + map.setSort(new SortSpec("gender")); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + ourLog.info("IDS: {}", ids); + assertThat(ids, containsInAnyOrder("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB", "Patient/CA")); + + map = new SearchParameterMap(); + map.setSort(new SortSpec("gender").setChain(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC)))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + ourLog.info("IDS: {}", ids); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB", "Patient/CA")); + + // Sort + map = new SearchParameterMap(); + map.add(Patient.SP_ACTIVE, new TokenParam(null, "true")); + map.setSort(new SortSpec("family", SortOrderEnum.ASC).setChain(new SortSpec("given", SortOrderEnum.ASC))); + ids = toUnqualifiedVersionlessIdValues(myPatientDao.search(map)); + assertThat(ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB")); + } + @Test public void testSearchWithUriParamAbove() throws Exception { ValueSet vs1 = new ValueSet(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java index e3fba8f5ec0..b5f3d403032 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java @@ -23,6 +23,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.config.TestDstu3WithoutLuceneConfig; import ca.uhn.fhir.jpa.dao.*; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; +import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -139,6 +140,8 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes @Autowired protected PlatformTransactionManager myTxManager; + @Autowired + protected ISearchParamPresenceSvc mySearchParamPresenceSvc; @Autowired @Qualifier("myJpaValidationSupportChainDstu3") @@ -148,7 +151,7 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes @Transactional() public void beforePurgeDatabase() { final EntityManager entityManager = this.myEntityManager; - purgeDatabase(entityManager, myTxManager); + purgeDatabase(entityManager, myTxManager, mySearchParamPresenceSvc); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu1Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu1Test.java index 20692cf385c..8bf29774d95 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu1Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu1Test.java @@ -39,6 +39,7 @@ import ca.uhn.fhir.jpa.dao.BaseJpaTest; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao; +import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.IResource; @@ -87,6 +88,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest { private static CloseableHttpClient ourHttpClient; private static EntityManager ourEntityManager; private static PlatformTransactionManager ourTxManager; + private static ISearchParamPresenceSvc ourSearchParamPresenceSvc; @AfterClass public static void afterClassClearContext() throws Exception { @@ -551,6 +553,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest { ourOrganizationDao = (IFhirResourceDao) ourAppCtx.getBean("myOrganizationDaoDstu1", IFhirResourceDao.class); ourEntityManager = ourAppCtx.getBean(EntityManager.class); ourTxManager = ourAppCtx.getBean(PlatformTransactionManager.class); + ourSearchParamPresenceSvc = ourAppCtx.getBean(ISearchParamPresenceSvc.class); List rpsDev = (List) ourAppCtx.getBean("myResourceProvidersDstu1", List.class); restServer.setResourceProviders(rpsDev); @@ -593,7 +596,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest { @Before public void before() { - super.purgeDatabase(ourEntityManager, ourTxManager); + super.purgeDatabase(ourEntityManager, ourTxManager, ourSearchParamPresenceSvc); } } 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 62aebcf5306..e9af8276d1c 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 @@ -409,7 +409,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor(); assertTrue(interceptor.isAddValidationResultsToResponseOperationOutcome()); interceptor.setFailOnSeverity(null); - + ourRestServer.registerInterceptor(interceptor); try { // Missing status, which is mandatory @@ -421,7 +421,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { ourLog.info(encodedOo); assertThat(encodedOo, containsString("cvc-complex-type.2.4.b")); assertThat(encodedOo, containsString("Successfully created resource \\\"Observation/")); - + interceptor.setAddValidationResultsToResponseOperationOutcome(false); outcome = ourClient.create().resource(obs).execute().getOperationOutcome(); encodedOo = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome); @@ -1498,7 +1498,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { */ @Test public void testEverythingWithLargeSet() throws Exception { - + String inputString = IOUtils.toString(getClass().getResourceAsStream("/david_big_bundle.json"), StandardCharsets.UTF_8); Bundle inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, inputString); inputBundle.setType(BundleType.TRANSACTION); @@ -1522,7 +1522,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { .execute(); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(responseBundle)); - + TreeSet ids = new TreeSet(); for (int i = 0; i < responseBundle.getEntry().size(); i++) { for (BundleEntryComponent nextEntry : responseBundle.getEntry()) { @@ -2169,7 +2169,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { } } - @Test public void testSaveAndRetrieveExistingNarrativeJson() { Patient p1 = new Patient(); @@ -3046,42 +3045,38 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { p.addName().addGiven("Sarah").setFamily("Graham"); ourClient.create().resource(p).execute(); - //@formatter:off Bundle resp = ourClient - .search() - .forResource(Patient.class) - .where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", methodName)) - .sort().ascending(Patient.FAMILY) - .sort().ascending(Patient.GIVEN) - .count(100) - .returnBundle(Bundle.class) - .execute(); - //@formatter:on + .search() + .forResource(Patient.class) + .where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", methodName)) + .sort().ascending(Patient.FAMILY) + .sort().ascending(Patient.GIVEN) + .count(100) + .returnBundle(Bundle.class) + .execute(); List names = toNameList(resp); ourLog.info(StringUtils.join(names, '\n')); - //@formatter:off assertThat(names, contains( // this matches in order only - "Daniel Adams", - "Aaron Alexis", - "Carol Allen", - "Ruth Black", - "Brian Brooks", - "Amy Clark", - "Susan Clark", - "Anthony Coleman", - "Lisa Coleman", - "Steven Coleman", - "Ruth Cook", - "Betty Davis", - "Joshua Diaz", - "Brian Gracia", - "Sarah Graham", - "Stephan Graham")); - //@formatter:om - + "Daniel Adams", + "Aaron Alexis", + "Carol Allen", + "Ruth Black", + "Brian Brooks", + "Amy Clark", + "Susan Clark", + "Anthony Coleman", + "Lisa Coleman", + "Steven Coleman", + "Ruth Cook", + "Betty Davis", + "Joshua Diaz", + "Brian Gracia", + "Sarah Graham", + "Stephan Graham")); + } /** @@ -3118,7 +3113,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { CloseableHttpResponse resp = ourHttpClient.execute(post); try { assertEquals(200, resp.getStatusLine().getStatusCode()); - String output= IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8); + String output = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8); ourLog.info(output); } finally { resp.close(); @@ -3157,7 +3152,8 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { ourLog.info(responseString); assertEquals(400, response.getStatusLine().getStatusCode()); OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString); - assertThat(oo.getIssue().get(0).getDiagnostics(), containsString("Can not update resource, request URL must contain an ID element for update (PUT) operation (it must be of the form [base]/[resource type]/[id])")); + assertThat(oo.getIssue().get(0).getDiagnostics(), + containsString("Can not update resource, request URL must contain an ID element for update (PUT) operation (it must be of the form [base]/[resource type]/[id])")); } finally { response.close(); } @@ -3223,10 +3219,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { // Try to update with the wrong ID in the resource body p1.setId("FOO"); p1.addAddress().addLine("NEWLINE"); - + String encoded = myFhirCtx.newJsonParser().encodeResourceToString(p1); ourLog.info(encoded); - + HttpPut put = new HttpPut(ourServerBase + "/Patient/" + p1id.getIdPart()); put.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"))); put.addHeader("Accept", Constants.CT_FHIR_JSON); @@ -3234,14 +3230,17 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { try { assertEquals(400, response.getStatusLine().getStatusCode()); OperationOutcome oo = myFhirCtx.newJsonParser().parseResource(OperationOutcome.class, new InputStreamReader(response.getEntity().getContent())); - assertEquals("Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"FOO\" does not match URL ID of \"" + p1id.getIdPart() + "\"", oo.getIssue().get(0).getDiagnostics()); + assertEquals( + "Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"FOO\" does not match URL ID of \"" + + p1id.getIdPart() + "\"", + oo.getIssue().get(0).getDiagnostics()); } finally { response.close(); } - + // Try to update with the no ID in the resource body - p1.setId((String)null); - + p1.setId((String) null); + encoded = myFhirCtx.newJsonParser().encodeResourceToString(p1); put = new HttpPut(ourServerBase + "/Patient/" + p1id.getIdPart()); put.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"))); @@ -3257,7 +3256,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { // Try to update with the to correct ID in the resource body p1.setId(p1id.getIdPart()); - + encoded = myFhirCtx.newJsonParser().encodeResourceToString(p1); put = new HttpPut(ourServerBase + "/Patient/" + p1id.getIdPart()); put.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"))); @@ -3270,7 +3269,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { } - @Test public void testUpdateRejectsInvalidTypes() throws InterruptedException { diff --git a/hapi-fhir-jpaserver-base/src/test/resources/logback-test.xml b/hapi-fhir-jpaserver-base/src/test/resources/logback-test.xml index ad8afddfcab..18d0d7e8d53 100644 --- a/hapi-fhir-jpaserver-base/src/test/resources/logback-test.xml +++ b/hapi-fhir-jpaserver-base/src/test/resources/logback-test.xml @@ -38,7 +38,7 @@ - +