diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index 5b77bb7c699..3b3970107e7 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index f0b687dd3e7..bd2caced4a3 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index c260587c709..db38d2480a4 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-batch/pom.xml b/hapi-fhir-batch/pom.xml index 8b0d7590023..c278af4d8a9 100644 --- a/hapi-fhir-batch/pom.xml +++ b/hapi-fhir-batch/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 76232254a48..79f37ad22c7 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -3,14 +3,14 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT pom HAPI FHIR BOM ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index 331407f0cc6..5d2b1cf2c69 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index d447ef77452..3505e68b538 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index 71ba06bdc1f..0083658941e 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index 41fedf5bbd2..c4751e261d2 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../hapi-deployable-pom diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index da20bab67c8..2469fbc253a 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index 6cfa818a106..96389e525f1 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index fccb65a9453..735413ca850 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 1cb0744fb95..1ed7701885f 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index 65cd8a3137b..c6010d81016 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index 18992338cba..3d8fb140f64 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3693-exclude-deleted-resources-with-forced-ids-from-bundle-total-in-searches.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3693-exclude-deleted-resources-with-forced-ids-from-bundle-total-in-searches.yaml new file mode 100644 index 00000000000..82cd5dafcb7 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3693-exclude-deleted-resources-with-forced-ids-from-bundle-total-in-searches.yaml @@ -0,0 +1,7 @@ +--- +type: fix +issue: 3693 +jira: SMILE-4185 +title: "Previously, deleted resources with client generated ids were being included in the +bundle total when searching by _id. This has been corrected by adding functionality to optionally filter +out deleted resources when resolving forced ids to persistent ids." diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index c05789b6fb9..ca8fb92c2c7 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index 33ee7390790..94ea1b90f4b 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index 44fcbe8d7b2..40058d1db1c 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 1fd2865dfce..f91bdf8868b 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IForcedIdDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IForcedIdDao.java index 229a32bbcd5..e878c6f81ed 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IForcedIdDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IForcedIdDao.java @@ -1,12 +1,13 @@ package ca.uhn.fhir.jpa.dao.data; +import ca.uhn.fhir.jpa.dao.data.custom.IForcedIdQueries; import ca.uhn.fhir.jpa.model.entity.ForcedId; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; -import java.util.Collection; import java.util.List; import java.util.Optional; @@ -29,10 +30,10 @@ import java.util.Optional; * limitations under the License. * #L% */ +@Repository +public interface IForcedIdDao extends JpaRepository, IHapiFhirJpaRepository, IForcedIdQueries { -public interface IForcedIdDao extends JpaRepository, IHapiFhirJpaRepository { - - @Query("SELECT f FROM ForcedId f WHERE myResourcePid IN (:resource_pids)") + @Query("SELECT f FROM ForcedId f WHERE f.myResourcePid IN (:resource_pids)") List findAllByResourcePid(@Param("resource_pids") List theResourcePids); @Query("SELECT f FROM ForcedId f WHERE f.myResourcePid = :resource_pid") @@ -41,54 +42,4 @@ public interface IForcedIdDao extends JpaRepository, IHapiFhirJp @Modifying @Query("DELETE FROM ForcedId t WHERE t.myId = :pid") void deleteByPid(@Param("pid") Long theId); - - /** - * This method returns a Collection where each row is an element in the collection. Each element in the collection - * is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way. - */ - @Query("" + - "SELECT " + - " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + - "FROM ForcedId f " + - "JOIN ResourceTable t ON t.myId = f.myResourcePid " + - "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id )") - Collection findAndResolveByForcedIdWithNoType(@Param("resource_type") String theResourceType, @Param("forced_id") Collection theForcedIds); - - /** - * This method returns a Collection where each row is an element in the collection. Each element in the collection - * is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way. - */ - @Query("" + - "SELECT " + - " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + - "FROM ForcedId f " + - "JOIN ResourceTable t ON t.myId = f.myResourcePid " + - "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND f.myPartitionIdValue IN :partition_id") - Collection findAndResolveByForcedIdWithNoTypeInPartition(@Param("resource_type") String theResourceType, @Param("forced_id") Collection theForcedIds, @Param("partition_id") Collection thePartitionId); - - - /** - * This method returns a Collection where each row is an element in the collection. Each element in the collection - * is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way. - */ - @Query("" + - "SELECT " + - " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + - "FROM ForcedId f " + - "JOIN ResourceTable t ON t.myId = f.myResourcePid " + - "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND f.myPartitionIdValue IS NULL") - Collection findAndResolveByForcedIdWithNoTypeInPartitionNull(@Param("resource_type") String theResourceType, @Param("forced_id") Collection theForcedIds); - - - /** - * This method returns a Collection where each row is an element in the collection. Each element in the collection - * is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way. - */ - @Query("" + - "SELECT " + - " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + - "FROM ForcedId f " + - "JOIN ResourceTable t ON t.myId = f.myResourcePid " + - "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND (f.myPartitionIdValue IS NULL OR f.myPartitionIdValue IN :partition_id)") - Collection findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(@Param("resource_type") String theNextResourceType, @Param("forced_id") Collection theNextIds, @Param("forced_id") List thePartitionIdsWithoutDefault); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdDaoImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdDaoImpl.java new file mode 100644 index 00000000000..ed0b9f6fb96 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdDaoImpl.java @@ -0,0 +1,123 @@ +package ca.uhn.fhir.jpa.dao.data.custom; + +import org.springframework.stereotype.Component; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.Collection; +import java.util.List; + +@Component +// Don't change the name of this class. Spring Data requires the name to match. +// See https://stackoverflow.com/questions/11880924/how-to-add-custom-method-to-spring-data-jpa +public class IForcedIdDaoImpl implements IForcedIdQueries { + + @PersistenceContext + private EntityManager myEntityManager; + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are not filtered. + */ + public Collection findAndResolveByForcedIdWithNoTypeIncludeDeleted(String theResourceType, Collection theForcedIds) { + return findAndResolveByForcedIdWithNoType(theResourceType, theForcedIds, false); + } + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. Be careful if you change this query in any way. + */ + public Collection findAndResolveByForcedIdWithNoType(String theResourceType, Collection theForcedIds, boolean theExcludeDeleted) { + String query = "" + + "SELECT " + + " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + + "FROM ForcedId f " + + "JOIN ResourceTable t ON t.myId = f.myResourcePid " + + "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id )"; + + if (theExcludeDeleted) { + query += " AND t.myDeleted IS NULL"; + } + + return myEntityManager.createQuery(query) + .setParameter("resource_type", theResourceType) + .setParameter("forced_id", theForcedIds) + .getResultList(); + } + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. Be careful if you change this query in any way. + */ + public Collection findAndResolveByForcedIdWithNoTypeInPartition(String theResourceType, Collection theForcedIds, Collection thePartitionId, boolean theExcludeDeleted) { + String query = "" + + "SELECT " + + " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + + "FROM ForcedId f " + + "JOIN ResourceTable t ON t.myId = f.myResourcePid " + + "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND f.myPartitionIdValue IN ( :partition_id )"; + + + if (theExcludeDeleted) { + query += " AND t.myDeleted IS NULL"; + } + + return myEntityManager.createQuery(query) + .setParameter("resource_type", theResourceType) + .setParameter("forced_id", theForcedIds) + .setParameter("partition_id", thePartitionId) + .getResultList(); + } + + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. Be careful if you change this query in any way. + */ + public Collection findAndResolveByForcedIdWithNoTypeInPartitionNull(String theResourceType, Collection theForcedIds, boolean theExcludeDeleted) { + String query = "" + + "SELECT " + + " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + + "FROM ForcedId f " + + "JOIN ResourceTable t ON t.myId = f.myResourcePid " + + "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND f.myPartitionIdValue IS NULL"; + + + if (theExcludeDeleted) { + query += " AND t.myDeleted IS NULL"; + } + + return myEntityManager.createQuery(query) + .setParameter("resource_type", theResourceType) + .setParameter("forced_id", theForcedIds) + .getResultList(); + } + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. Be careful if you change this query in any way. + */ + public Collection findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(String theResourceType, Collection theForcedIds, List thePartitionIdsWithoutDefault, boolean theExcludeDeleted) { + String query = "" + + "SELECT " + + " f.myResourceType, f.myResourcePid, f.myForcedId, t.myDeleted " + + "FROM ForcedId f " + + "JOIN ResourceTable t ON t.myId = f.myResourcePid " + + "WHERE f.myResourceType = :resource_type AND f.myForcedId IN ( :forced_id ) AND (f.myPartitionIdValue IS NULL OR f.myPartitionIdValue IN ( :partition_id ))"; + + if (theExcludeDeleted) { + query += " AND t.myDeleted IS NULL"; + } + + return myEntityManager.createQuery(query) + .setParameter("resource_type", theResourceType) + .setParameter("forced_id", theForcedIds) + .setParameter("partition_id", thePartitionIdsWithoutDefault) + .getResultList(); + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdQueries.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdQueries.java new file mode 100644 index 00000000000..454793df1c3 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/custom/IForcedIdQueries.java @@ -0,0 +1,63 @@ +package ca.uhn.fhir.jpa.dao.data.custom; + +import java.util.Collection; +import java.util.List; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2022 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +public interface IForcedIdQueries { + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources should not be filtered. + */ + Collection findAndResolveByForcedIdWithNoTypeIncludeDeleted(String theResourceType, Collection theForcedIds); + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. + */ + Collection findAndResolveByForcedIdWithNoType(String theResourceType, Collection theForcedIds, boolean theExcludeDeleted); + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. + */ + Collection findAndResolveByForcedIdWithNoTypeInPartition(String theResourceType, Collection theForcedIds, Collection thePartitionId, boolean theExcludeDeleted); + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. + */ + Collection findAndResolveByForcedIdWithNoTypeInPartitionNull(String theResourceType, Collection theForcedIds, boolean theExcludeDeleted); + + /** + * This method returns a Collection where each row is an element in the collection. Each element in the collection + * is an object array, where the order matters (the array represents columns returned by the query). + * Deleted resources are optionally filtered. + */ + Collection findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(String theNextResourceType, Collection theNextIds, List thePartitionIdsWithoutDefault, boolean theExcludeDeleted); + +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java index 709d5c3f9fc..eebf2158ec7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java @@ -31,7 +31,6 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.cross.IResourceLookup; import ca.uhn.fhir.jpa.model.cross.ResourceLookup; import ca.uhn.fhir.jpa.model.entity.ForcedId; -import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.search.builder.SearchBuilder; import ca.uhn.fhir.jpa.util.MemoryCacheService; import ca.uhn.fhir.jpa.util.QueryChunker; @@ -128,12 +127,26 @@ public class IdHelperService implements IIdHelperService { @Override @Nonnull public IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId) throws ResourceNotFoundException { + return resolveResourceIdentity(theRequestPartitionId, theResourceType, theResourceId, false); + } + + /** + * Given a forced ID, convert it to its Long value. Since you are allowed to use string IDs for resources, we need to + * convert those to the underlying Long values that are stored, for lookup and comparison purposes. + * Optionally filters out deleted resources. + * + * @throws ResourceNotFoundException If the ID can not be found + */ + @Override + @Nonnull + public IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId, boolean theExcludeDeleted) throws ResourceNotFoundException { assert myDontCheckActiveTransactionForUnitTest || TransactionSynchronizationManager.isSynchronizationActive(); assert theRequestPartitionId != null; IdDt id = new IdDt(theResourceType, theResourceId); Map> matches = translateForcedIdToPids(theRequestPartitionId, - Collections.singletonList(id)); + Collections.singletonList(id), + theExcludeDeleted); // We only pass 1 input in so only 0..1 will come back if (matches.isEmpty() || !matches.containsKey(theResourceId)) { @@ -155,14 +168,27 @@ public class IdHelperService implements IIdHelperService { /** * Returns a mapping of Id -> ResourcePersistentId. - * If any resource is not found, it will throw ResourceNotFound exception - * (and no map will be returned) + * If any resource is not found, it will throw ResourceNotFound exception (and no map will be returned) */ @Override @Nonnull public Map resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, List theIds) { + return resolveResourcePersistentIds(theRequestPartitionId, theResourceType, theIds, false); + } + + /** + * Returns a mapping of Id -> ResourcePersistentId. + * If any resource is not found, it will throw ResourceNotFound exception (and no map will be returned) + * Optionally filters out deleted resources. + */ + @Override + @Nonnull + public Map resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, + String theResourceType, + List theIds, + boolean theExcludeDeleted) { assert myDontCheckActiveTransactionForUnitTest || TransactionSynchronizationManager.isSynchronizationActive(); Validate.notNull(theIds, "theIds cannot be null"); Validate.isTrue(!theIds.isEmpty(), "theIds must not be empty"); @@ -179,7 +205,7 @@ public class IdHelperService implements IIdHelperService { // is a forced id // we must resolve! if (myDaoConfig.isDeleteEnabled()) { - retVal = new ResourcePersistentId(resolveResourceIdentity(theRequestPartitionId, theResourceType, id).getResourceId()); + retVal = new ResourcePersistentId(resolveResourceIdentity(theRequestPartitionId, theResourceType, id, theExcludeDeleted).getResourceId()); retVals.put(id, retVal); } else { // fetch from cache... adding to cache if not available @@ -209,11 +235,22 @@ public class IdHelperService implements IIdHelperService { @Override @Nonnull public ResourcePersistentId resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId) { + return resolveResourcePersistentIds(theRequestPartitionId, theResourceType, theId, false); + } + + /** + * Given a resource type and ID, determines the internal persistent ID for the resource. + * Optionally filters out deleted resources. + * + * @throws ResourceNotFoundException If the ID can not be found + */ + public ResourcePersistentId resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId, boolean theExcludeDeleted){ Validate.notNull(theId, "theId must not be null"); Map retVal = resolveResourcePersistentIds(theRequestPartitionId, theResourceType, - Collections.singletonList(theId)); + Collections.singletonList(theId), + theExcludeDeleted); return retVal.get(theId); // should be only one } @@ -406,7 +443,7 @@ public class IdHelperService implements IIdHelperService { return typeToIds; } - private Map> translateForcedIdToPids(@Nonnull RequestPartitionId theRequestPartitionId, Collection theId) { + private Map> translateForcedIdToPids(@Nonnull RequestPartitionId theRequestPartitionId, Collection theId, boolean theExcludeDeleted) { assert theRequestPartitionId != null; theId.forEach(id -> Validate.isTrue(id.hasIdPart())); @@ -455,14 +492,14 @@ public class IdHelperService implements IIdHelperService { assert isNotBlank(nextResourceType); if (requestPartitionId.isAllPartitions()) { - views = myForcedIdDao.findAndResolveByForcedIdWithNoType(nextResourceType, nextIds); + views = myForcedIdDao.findAndResolveByForcedIdWithNoType(nextResourceType, nextIds, theExcludeDeleted); } else { if (requestPartitionId.isDefaultPartition()) { - views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull(nextResourceType, nextIds); + views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull(nextResourceType, nextIds, theExcludeDeleted); } else if (requestPartitionId.hasDefaultPartitionId()) { - views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(nextResourceType, nextIds, requestPartitionId.getPartitionIdsWithoutDefault()); + views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(nextResourceType, nextIds, requestPartitionId.getPartitionIdsWithoutDefault(), theExcludeDeleted); } else { - views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition(nextResourceType, nextIds, requestPartitionId.getPartitionIds()); + views = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition(nextResourceType, nextIds, requestPartitionId.getPartitionIds(), theExcludeDeleted); } } @@ -471,6 +508,7 @@ public class IdHelperService implements IIdHelperService { Long resourcePid = (Long) next[1]; String forcedId = (String) next[2]; Date deletedAt = (Date) next[3]; + ResourceLookup lookup = new ResourceLookup(resourceType, resourcePid, deletedAt); if (!retVal.containsKey(forcedId)) { retVal.put(forcedId, new ArrayList<>()); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceIdPredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceIdPredicateBuilder.java index 10d37452c9b..f9701cb3bd0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceIdPredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceIdPredicateBuilder.java @@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.search.builder.predicate; import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.predicate.SearchFilterParser; import ca.uhn.fhir.jpa.search.builder.QueryStack; import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder; @@ -83,7 +82,8 @@ public class ResourceIdPredicateBuilder extends BasePredicateBuilder { } haveValue = true; try { - ResourcePersistentId pid = myIdHelperService.resolveResourcePersistentIds(theRequestPartitionId, theResourceName, valueAsId.getIdPart()); + boolean excludeDeleted = true; + ResourcePersistentId pid = myIdHelperService.resolveResourcePersistentIds(theRequestPartitionId, theResourceName, valueAsId.getIdPart(), excludeDeleted); orPids.add(pid); } catch (ResourceNotFoundException e) { // This is not an error in a search, it just results in no matches diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml index f30903e08d7..91f9a04d4b0 100644 --- a/hapi-fhir-jpaserver-cql/pom.xml +++ b/hapi-fhir-jpaserver-cql/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 216b0f95e4b..9bdb6c6cbc4 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 403189b82a9..adee5916e39 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 2452a4c8207..7720639b238 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 591e61ba150..82ce2a02907 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 552f06e9a72..960a0c77b71 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/index/IdHelperServiceTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/index/IdHelperServiceTest.java index e335c44d614..da24c44bde0 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/index/IdHelperServiceTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/index/IdHelperServiceTest.java @@ -2,9 +2,9 @@ package ca.uhn.fhir.jpa.dao.index; import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.jpa.api.config.DaoConfig; -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; import ca.uhn.fhir.jpa.dao.data.IForcedIdDao; import ca.uhn.fhir.jpa.model.config.PartitionSettings; +import ca.uhn.fhir.jpa.model.cross.IResourceLookup; import ca.uhn.fhir.jpa.util.MemoryCacheService; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import org.hl7.fhir.r4.model.Patient; @@ -18,12 +18,21 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.function.Function; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.when; + @ExtendWith(MockitoExtension.class) public class IdHelperServiceTest { @@ -88,10 +97,10 @@ public class IdHelperServiceTest { }; // when - Mockito.when(myDaoConfig.isDeleteEnabled()) + when(myDaoConfig.isDeleteEnabled()) .thenReturn(true); - Mockito.when(myForcedIdDao.findAndResolveByForcedIdWithNoType(Mockito.anyString(), - Mockito.anyList())) + when(myForcedIdDao.findAndResolveByForcedIdWithNoType(Mockito.anyString(), + Mockito.anyList(), Mockito.anyBoolean())) .thenReturn(Collections.singletonList(redView)) .thenReturn(Collections.singletonList(blueView)); @@ -119,9 +128,9 @@ public class IdHelperServiceTest { ResourcePersistentId blue = new ResourcePersistentId("Patient", new Long(456l)); // we will pretend the lookup value is in the cache - Mockito.when(myMemoryCacheService.getThenPutAfterCommit(Mockito.any(MemoryCacheService.CacheEnum.class), + when(myMemoryCacheService.getThenPutAfterCommit(any(MemoryCacheService.CacheEnum.class), Mockito.anyString(), - Mockito.any(Function.class))) + any(Function.class))) .thenReturn(red) .thenReturn(blue); @@ -139,4 +148,58 @@ public class IdHelperServiceTest { Assertions.assertEquals(red, map.get("RED")); Assertions.assertEquals(blue, map.get("BLUE")); } + + @Test + public void testResolveResourceIdentity_defaultFunctionality(){ + RequestPartitionId partitionId = RequestPartitionId.fromPartitionIdAndName(1, "partition"); + String resourceType = "Patient"; + String resourceForcedId = "AAA"; + + Object[] forcedIdView = new Object[4]; + forcedIdView[0] = resourceType; + forcedIdView[1] = 1L; + forcedIdView[2] = resourceForcedId; + forcedIdView[3] = null; + + Collection testForcedIdViews = new ArrayList<>(); + testForcedIdViews.add(forcedIdView); + when(myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition(any(), any(), any(), anyBoolean())).thenReturn(testForcedIdViews); + + IResourceLookup result = myHelperService.resolveResourceIdentity(partitionId, resourceType, resourceForcedId); + assertEquals(forcedIdView[0], result.getResourceType()); + assertEquals(forcedIdView[1], result.getResourceId()); + assertEquals(forcedIdView[3], result.getDeleted()); + } + + @Test + public void testResolveResourcePersistentIds_mapDefaultFunctionality(){ + RequestPartitionId partitionId = RequestPartitionId.fromPartitionIdAndName(1, "partition"); + String resourceType = "Patient"; + List ids = Arrays.asList("A", "B", "C"); + + ResourcePersistentId resourcePersistentId1 = new ResourcePersistentId("TEST1"); + ResourcePersistentId resourcePersistentId2 = new ResourcePersistentId("TEST2"); + ResourcePersistentId resourcePersistentId3 = new ResourcePersistentId("TEST3"); + when(myMemoryCacheService.getThenPutAfterCommit(any(), any(), any())) + .thenReturn(resourcePersistentId1) + .thenReturn(resourcePersistentId2) + .thenReturn(resourcePersistentId3); + Map result = myHelperService.resolveResourcePersistentIds(partitionId, resourceType, ids); + assertThat(result.keySet(), hasSize(3)); + assertEquals("TEST1", result.get("A").getId()); + assertEquals("TEST2", result.get("B").getId()); + assertEquals("TEST3", result.get("C").getId()); + } + + @Test + public void testResolveResourcePersistentIds_resourcePidDefaultFunctionality(){ + RequestPartitionId partitionId = RequestPartitionId.fromPartitionIdAndName(1, "partition"); + String resourceType = "Patient"; + String id = "A"; + + ResourcePersistentId resourcePersistentId1 = new ResourcePersistentId(id); + when(myMemoryCacheService.getThenPutAfterCommit(any(), any(), any())).thenReturn(resourcePersistentId1); + ResourcePersistentId result = myHelperService.resolveResourcePersistentIds(partitionId, resourceType, id); + assertEquals(id, result.getId()); + } } diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java index 743fcd352cd..2d3dc623cff 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java @@ -877,8 +877,8 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test { assertEquals(1, StringUtils.countMatches(selectQuery.toLowerCase(), "t0.res_deleted_at is null"), selectQuery); } - // Delete the resource - The searches should generate similar SQL now, but - // not actually return the result + // Delete the resource - There should only be one search performed because deleted resources will + // be filtered out in the query that resolves forced ids to persistent ids myObservationDao.delete(new IdType("Observation/A")); myObservationDao.delete(new IdType("Observation/" + obs2id)); @@ -892,14 +892,10 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test { assertEquals(0, outcome.getResources(0, 999).size()); myCaptureQueriesListener.logSelectQueriesForCurrentThread(); + assertEquals(1, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size()); String selectQuery = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, false); assertEquals(1, StringUtils.countMatches(selectQuery.toLowerCase(), "forcedid0_.resource_type='observation'"), selectQuery); assertEquals(1, StringUtils.countMatches(selectQuery.toLowerCase(), "forcedid0_.forced_id in ('a')"), selectQuery); - - selectQuery = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(1).getSql(true, false); - assertEquals(1, StringUtils.countMatches(selectQuery.toLowerCase(), "select t0.res_id from hfj_resource t0"), selectQuery); - assertEquals(0, StringUtils.countMatches(selectQuery.toLowerCase(), "t0.res_type = 'observation'"), selectQuery); - assertEquals(0, StringUtils.countMatches(selectQuery.toLowerCase(), "t0.res_deleted_at is null"), selectQuery); } // Search by ID where at least one ID is a numeric ID diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantServerR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantServerR4Test.java index 4909770a140..6563bc96976 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantServerR4Test.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantServerR4Test.java @@ -36,6 +36,8 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; import java.util.Date; import static org.hamcrest.MatcherAssert.assertThat; @@ -151,6 +153,187 @@ public class MultitenantServerR4Test extends BaseMultitenantResourceProviderR4Te } } + @Test + public void testFindAndResolveByForcedIdWithNoType() { + // Create patients + String patientId = "AAA"; + IIdType idA = createPatient(withId(patientId)); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeIncludeDeleted( + "Patient", Arrays.asList(patientId) + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoType( + "Patient", Arrays.asList(patientId), true + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Delete resource + deletePatient(JpaConstants.DEFAULT_PARTITION_NAME, idA); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeIncludeDeleted( + "Patient", Arrays.asList(patientId) + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoType( + "Patient", Arrays.asList(patientId), true + ); + assertThat(forcedIds, hasSize(0)); + }); + } + + @Test + public void findAndResolveByForcedIdWithNoTypeInPartitionNull() { + // Create patients + String patientId = "AAA"; + IIdType idA = createPatient(withId(patientId)); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull( + "Patient", Arrays.asList(patientId), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull( + "Patient", Arrays.asList(patientId), true + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Delete resource + deletePatient(JpaConstants.DEFAULT_PARTITION_NAME, idA); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull( + "Patient", Arrays.asList(patientId), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionNull( + "Patient", Arrays.asList(patientId), true + ); + assertEquals(0, forcedIds.size()); + }); + } + + @Test + public void testFindAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId(){ + // Create patients + String patientId = "AAA"; + IIdType idA = createPatient(withTenant(TENANT_A), withId(patientId)); + + createPatient(withId("BBB")); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID), true + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + deletePatient(TENANT_A, idA); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartitionIdOrNullPartitionId( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID), true + ); + assertEquals(0, forcedIds.size()); + }); + } + + @Test + public void testFindAndResolveByForcedIdWithNoTypeInPartition() throws IOException { + // Create patients + String patientId = "AAA"; + IIdType idA = createPatient(withTenant(TENANT_A), withId(patientId)); + + createPatient(withTenant(TENANT_B), withId("BBB")); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID, TENANT_B_ID), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID, TENANT_B_ID), true + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + deletePatient(TENANT_A, idA); + + // Search and include deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID, TENANT_B_ID), false + ); + assertContainsSingleForcedId(forcedIds, patientId); + }); + + // Search and filter deleted + runInTransaction(() -> { + Collection forcedIds = myForcedIdDao.findAndResolveByForcedIdWithNoTypeInPartition( + "Patient", Arrays.asList(patientId), Arrays.asList(TENANT_A_ID, TENANT_B_ID), true + ); + assertEquals(0, forcedIds.size()); + }); + } + + private void assertContainsSingleForcedId(Collection forcedIds, String patientId){ + assertEquals(1, forcedIds.size()); + assertEquals(patientId, forcedIds.stream().toList().get(0)[2]); + } + + private void deletePatient(String tenantId, IIdType patientId){ + SystemRequestDetails requestDetails = new SystemRequestDetails(); + requestDetails.setTenantId(tenantId); + myPatientDao.delete(patientId, requestDetails); + } + @Test public void testCreateAndRead_NonPartitionableResource_DefaultTenant() { diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index 58b7d383543..93ff56771b6 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -45,6 +45,7 @@ import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.UrlUtil; import com.google.common.base.Charsets; import com.google.common.collect.Lists; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; @@ -3986,6 +3987,74 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } + @Test + public void testSearchByIdForDeletedResourceWithClientAssignedId() throws IOException { + // Create with client assigned ID + Patient p = new Patient(); + String patientId = "AAA"; + p.setId(patientId); + + MethodOutcome outcome = myClient.update().resource(p).execute(); + assertTrue(outcome.getCreated()); + + Patient createdPatient = (Patient) outcome.getResource(); + + // Search + Bundle search1 = (Bundle) myClient.search() + .forResource(Patient.class) + .where(Patient.RES_ID.exactly().identifier(patientId)) + .execute(); + + assertEquals(1, search1.getTotal()); + assertEquals(patientId, search1.getEntry().get(0).getResource().getIdElement().getIdPart()); + + // Delete + outcome = myClient.delete().resource(createdPatient).execute(); + assertNull(outcome.getResource()); + + // Search + Bundle search2 = (Bundle) myClient.search() + .forResource(Patient.class) + .where(Patient.RES_ID.exactly().identifier(patientId)) + .execute(); + + assertTrue(CollectionUtils.isEmpty(search2.getEntry())); + assertEquals(0, search2.getTotal()); + } + + @Test + public void testSearchByIdForDeletedResourceWithServerAssignedId() throws IOException { + // Create with server assigned ID + Patient p = new Patient(); + MethodOutcome outcome = myClient.create().resource(p).execute(); + assertTrue(outcome.getCreated()); + + Patient createdPatient = (Patient) outcome.getResource(); + String patientId = createdPatient.getIdElement().getIdPart(); + + // Search + Bundle search1 = (Bundle) myClient.search() + .forResource(Patient.class) + .where(Patient.RES_ID.exactly().identifier(patientId)) + .execute(); + + assertEquals(1, search1.getTotal()); + assertEquals(patientId, search1.getEntry().get(0).getResource().getIdElement().getIdPart()); + + // Delete + outcome = myClient.delete().resource(createdPatient).execute(); + assertNull(outcome.getResource()); + + // Search + Bundle search2 = (Bundle) myClient.search() + .forResource(Patient.class) + .where(Patient.RES_ID.exactly().identifier(patientId)) + .execute(); + + assertTrue(CollectionUtils.isEmpty(search2.getEntry())); + assertEquals(0, search2.getTotal()); + } + @Test public void testSearchByIdentifier() { Patient p1 = new Patient(); diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index aa4322b108d..08fc2ef31cc 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index 1bf886b484e..542dfa9e1f8 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index a9bfa7583a6..d69a8163bda 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index 557255b5c0a..4d2fdba8523 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 9ef3c2434f8..cb05689ecbe 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index 7064c2403a6..a742e69d87e 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index 688a0b38ac3..d7bc02cccd9 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT hapi-fhir-spring-boot-sample-client-okhttp diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index faf9aded181..ab84da3e38b 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT hapi-fhir-spring-boot-sample-server-jersey diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index e0d19e72510..7408fddec99 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT hapi-fhir-spring-boot-samples diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 109120ec8ad..b2b0e5c1603 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 3a46299a468..1e8a9855073 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index 06af89a1e96..499471d8307 100644 --- a/hapi-fhir-sql-migrate/pom.xml +++ b/hapi-fhir-sql-migrate/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml index 3cc451d260f..d31928085fe 100644 --- a/hapi-fhir-storage-batch2-jobs/pom.xml +++ b/hapi-fhir-storage-batch2-jobs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index 61faeb957a6..8e288cc7e3e 100644 --- a/hapi-fhir-storage-batch2/pom.xml +++ b/hapi-fhir-storage-batch2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index 7839febf086..4c19fcbc852 100644 --- a/hapi-fhir-storage-mdm/pom.xml +++ b/hapi-fhir-storage-mdm/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index c87e476b9ce..a1bd83d8bb8 100644 --- a/hapi-fhir-storage-test-utilities/pom.xml +++ b/hapi-fhir-storage-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index 273a57bfd2b..aa95daca34e 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/svc/IIdHelperService.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/svc/IIdHelperService.java index 6b2b97f1333..bdb6bf54cb8 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/svc/IIdHelperService.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/api/svc/IIdHelperService.java @@ -60,6 +60,15 @@ public interface IIdHelperService { @Nonnull ResourcePersistentId resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId); + /** + * Given a resource type and ID, determines the internal persistent ID for a resource. + * Optionally filters out deleted resources. + * + * @throws ResourceNotFoundException If the ID can not be found + */ + @Nonnull + ResourcePersistentId resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId, boolean theExcludeDeleted); + /** * Returns a mapping of Id -> ResourcePersistentId. * If any resource is not found, it will throw ResourceNotFound exception @@ -68,6 +77,14 @@ public interface IIdHelperService { @Nonnull Map resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, List theIds); + /** + * Returns a mapping of Id -> ResourcePersistentId. + * If any resource is not found, it will throw ResourceNotFound exception (and no map will be returned) + * Optionally filters out deleted resources. + */ + @Nonnull + Map resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, List theIds, boolean theExcludeDeleted); + /** * Given a persistent ID, returns the associated resource ID */ @@ -83,6 +100,16 @@ public interface IIdHelperService { @Nonnull IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId) throws ResourceNotFoundException; + /** + * Given a forced ID, convert it to it's Long value. Since you are allowed to use string IDs for resources, we need to + * convert those to the underlying Long values that are stored, for lookup and comparison purposes. + * Optionally filters out deleted resources. + * + * @throws ResourceNotFoundException If the ID can not be found + */ + @Nonnull + IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId, boolean theExcludeDeleted) throws ResourceNotFoundException; + /** * Returns true if the given resource ID should be stored in a forced ID. Under default config * (meaning client ID strategy is {@link ca.uhn.fhir.jpa.api.config.DaoConfig.ClientIdStrategyEnum#ALPHANUMERIC}) diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index 3762cadc0cf..431ac1b9ae1 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index f9157fc2812..6179432fdb6 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 0dd0637dd62..96f27edb1e7 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index a51e975ee73..8cb9824d969 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index fb8db0fdd14..09fccf64480 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 70fc343083e..ec73bd3200a 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index b06aed3c050..c562ec2b7dc 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 37b27852529..c04e70fda34 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index b010cb08adf..2d0e8f05505 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 2345b71bfb0..600970ecac7 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index b6547cde78c..be42fb8f35a 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index 7c35f2b7a57..b988f351eef 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index c3c15da8e4e..7fb3f309e83 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index fb19dbdab92..7eff347e8fb 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 97bb8b405de..328dae44b62 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml @@ -58,37 +58,37 @@ ca.uhn.hapi.fhir hapi-fhir-structures-dstu3 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-hl7org-dstu2 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r4 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r5 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu2 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu3 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-r4 - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT org.apache.velocity diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 34ece9e51be..2ae443f68e7 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 55d9460658f..4f79b5b8cd1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. https://hapifhir.io @@ -2011,7 +2011,7 @@ ca.uhn.hapi.fhir hapi-fhir-checkstyle - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index b72ccf38330..dbc7b4ea802 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index 9017a08f43e..7ae5c0c97e1 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index 7ca31ee1dc4..e0ad30b8d40 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE8-SNAPSHOT + 6.1.0-PRE9-SNAPSHOT ../../pom.xml