Update resource provenance indexing strategy (#4883)
* Add migration * Update indexes * Update hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java Co-authored-by: michaelabuckley <michaelabuckley@gmail.com> * Address review comments * Test fixes * Test fixes * Test fix --------- Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
This commit is contained in:
parent
54cec79a65
commit
1c66e57465
|
@ -1 +1,7 @@
|
|||
Users of the `Resource.meta.source` field, as well as users of the `_source` parameter should perform a global $reindex after upgrading to this version of HAPI FHIR with the following parameters:
|
||||
|
||||
```url
|
||||
[base]/$reindex?reindexSearchParameters=false&optimizeStorage=ALL_VERSIONS
|
||||
```
|
||||
|
||||
The previous mechanism for storing and indexing these parameters is inefficient and will be replaced in a future release of HAPI FHIR. Performing this reindex operation ensures that existing data will continue to be searchable.
|
||||
|
|
|
@ -1336,10 +1336,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
provenance.setResourceTable(theEntity);
|
||||
provenance.setPartitionId(theEntity.getPartitionId());
|
||||
if (haveRequestId) {
|
||||
provenance.setRequestId(left(requestId, Constants.REQUEST_ID_LENGTH));
|
||||
String persistedRequestId = left(requestId, Constants.REQUEST_ID_LENGTH);
|
||||
provenance.setRequestId(persistedRequestId);
|
||||
historyEntry.setRequestId(persistedRequestId);
|
||||
}
|
||||
if (haveSource) {
|
||||
provenance.setSourceUri(source);
|
||||
String persistedSource = left(source, ResourceHistoryTable.SOURCE_URI_LENGTH);
|
||||
provenance.setSourceUri(persistedSource);
|
||||
historyEntry.setSourceUri(persistedSource);
|
||||
}
|
||||
if (theResource != null) {
|
||||
MetaUtil.populateResourceSource(myFhirContext, shouldStoreSource ? source : null, shouldStoreRequestId ? requestId : null , theResource);
|
||||
|
|
|
@ -1439,8 +1439,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
reindexOptimizeStorageHistoryEntity(entity, historyEntity);
|
||||
if (theOptimizeStorageMode == ReindexParameters.OptimizeStorageModeEnum.ALL_VERSIONS) {
|
||||
int pageSize = 100;
|
||||
for (int page = 0; ((long) page * pageSize) < entity.getVersion(); page++) {
|
||||
Slice<ResourceHistoryTable> historyEntities = myResourceHistoryTableDao.findForResourceIdAndReturnEntities(PageRequest.of(page, pageSize), entity.getId(), historyEntity.getVersion());
|
||||
for (int page = 0; ((long)page * pageSize) < entity.getVersion(); page++) {
|
||||
Slice<ResourceHistoryTable> historyEntities = myResourceHistoryTableDao.findForResourceIdAndReturnEntitiesAndFetchProvenance(PageRequest.of(page, pageSize), entity.getId(), historyEntity.getVersion());
|
||||
for (ResourceHistoryTable next : historyEntities) {
|
||||
reindexOptimizeStorageHistoryEntity(entity, next);
|
||||
}
|
||||
|
@ -1450,16 +1450,30 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
private void reindexOptimizeStorageHistoryEntity(ResourceTable entity, ResourceHistoryTable historyEntity) {
|
||||
boolean changed = false;
|
||||
if (historyEntity.getEncoding() == ResourceEncodingEnum.JSONC || historyEntity.getEncoding() == ResourceEncodingEnum.JSON) {
|
||||
byte[] resourceBytes = historyEntity.getResource();
|
||||
if (resourceBytes != null) {
|
||||
String resourceText = decodeResource(resourceBytes, historyEntity.getEncoding());
|
||||
if (myStorageSettings.getInlineResourceTextBelowSize() > 0 && resourceText.length() < myStorageSettings.getInlineResourceTextBelowSize()) {
|
||||
ourLog.debug("Storing text of resource {} version {} as inline VARCHAR", entity.getResourceId(), historyEntity.getVersion());
|
||||
myResourceHistoryTableDao.setResourceTextVcForVersion(historyEntity.getId(), resourceText);
|
||||
historyEntity.setResourceTextVc(resourceText);
|
||||
historyEntity.setResource(null);
|
||||
historyEntity.setEncoding(ResourceEncodingEnum.JSON);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isBlank(historyEntity.getSourceUri()) && isBlank(historyEntity.getRequestId())) {
|
||||
if (historyEntity.getProvenance() != null) {
|
||||
historyEntity.setSourceUri(historyEntity.getProvenance().getSourceUri());
|
||||
historyEntity.setRequestId(historyEntity.getProvenance().getRequestId());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
myResourceHistoryTableDao.save(historyEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private BaseHasResource readEntity(IIdType theId, boolean theCheckForForcedId, RequestDetails theRequest, RequestPartitionId requestPartitionId) {
|
||||
|
|
|
@ -44,8 +44,8 @@ public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryT
|
|||
@Query("SELECT t.myId FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion != :dontWantVersion")
|
||||
Slice<Long> findForResourceId(Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
|
||||
@Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion != :dontWantVersion")
|
||||
Slice<ResourceHistoryTable> findForResourceIdAndReturnEntities(Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
@Query("SELECT t FROM ResourceHistoryTable t LEFT OUTER JOIN FETCH t.myProvenance WHERE t.myResourceId = :resId AND t.myResourceVersion != :dontWantVersion")
|
||||
Slice<ResourceHistoryTable> findForResourceIdAndReturnEntitiesAndFetchProvenance(Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
|
||||
@Query("" +
|
||||
"SELECT v.myId FROM ResourceHistoryTable v " +
|
||||
|
@ -67,13 +67,6 @@ public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryT
|
|||
"WHERE v.myResourceVersion != t.myVersion")
|
||||
Slice<Long> findIdsOfPreviousVersionsOfResources(Pageable thePage);
|
||||
|
||||
/**
|
||||
* Sets the inline text and clears the LOB copy of the text
|
||||
*/
|
||||
@Modifying
|
||||
@Query("UPDATE ResourceHistoryTable as t SET t.myResource = null, t.myResourceTextVc = :text WHERE t.myId = :pid")
|
||||
void setResourceTextVcForVersion(@Param("pid") Long id, @Param("text") String resourceText);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE ResourceHistoryTable r SET r.myResourceVersion = :newVersion WHERE r.myResourceId = :id AND r.myResourceVersion = :oldVersion")
|
||||
void updateVersion(@Param("id") long theId, @Param("oldVersion") long theOldVersion, @Param("newVersion") long theNewVersion);
|
||||
|
@ -81,4 +74,5 @@ public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryT
|
|||
@Modifying
|
||||
@Query("DELETE FROM ResourceHistoryTable t WHERE t.myId = :pid")
|
||||
void deleteByPid(@Param("pid") Long theId);
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
|
|||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
@ -43,6 +44,7 @@ import javax.persistence.TemporalType;
|
|||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@SuppressWarnings("SqlDialectInspection")
|
||||
@Entity
|
||||
@Immutable
|
||||
@Subselect("SELECT h.pid as pid, " +
|
||||
|
@ -83,7 +85,7 @@ public class ResourceSearchView implements IBaseResourceEntity, Serializable {
|
|||
private Long myResourceVersion;
|
||||
@Column(name = "PROV_REQUEST_ID", length = Constants.REQUEST_ID_LENGTH)
|
||||
private String myProvenanceRequestId;
|
||||
@Column(name = "PROV_SOURCE_URI", length = ResourceHistoryProvenanceEntity.SOURCE_URI_LENGTH)
|
||||
@Column(name = "PROV_SOURCE_URI", length = ResourceHistoryTable.SOURCE_URI_LENGTH)
|
||||
private String myProvenanceSourceUri;
|
||||
@Column(name = "HAS_TAGS")
|
||||
private boolean myHasTags;
|
||||
|
|
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.jpa.migrate.tasks.api.BaseMigrationTasks;
|
|||
import ca.uhn.fhir.jpa.migrate.tasks.api.Builder;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
|
@ -120,8 +121,24 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
.online(false)
|
||||
.withColumns("TAG_TYPE", "TAG_CODE", "TAG_SYSTEM", "TAG_ID", "TAG_VERSION", "TAG_USER_SELECTED");
|
||||
|
||||
version.onTable("HFJ_RES_VER_PROV")
|
||||
.addIndex("20230510.1", "IDX_RESVERPROV_RES_VER_PID")
|
||||
.unique(false)
|
||||
.withColumns("RES_VER_PID")
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RES_VER_PROV")
|
||||
.addIndex("20230510.2", "IDX_RESVERPROV_RES_PID")
|
||||
.unique(false)
|
||||
.withColumns("RES_PID");
|
||||
|
||||
|
||||
version.onTable(ResourceHistoryTable.HFJ_RES_VER)
|
||||
.addColumn("20230510.4", "SOURCE_URI")
|
||||
.nullable()
|
||||
.type(ColumnTypeEnum.STRING, 100);
|
||||
version.onTable(ResourceHistoryTable.HFJ_RES_VER)
|
||||
.addColumn("20230510.5", "REQUEST_ID")
|
||||
.nullable()
|
||||
.type(ColumnTypeEnum.STRING, 16);
|
||||
}
|
||||
|
||||
protected void init660() {
|
||||
|
|
|
@ -949,12 +949,6 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
}
|
||||
}
|
||||
|
||||
private Consumer<IBaseResource>[] asArray(Consumer<IBaseResource> theIBaseResourceConsumer) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Consumer<IBaseResource>[] array = (Consumer<IBaseResource>[]) new Consumer[]{theIBaseResourceConsumer};
|
||||
return array;
|
||||
}
|
||||
|
||||
private List<String> getResultIds(IBundleProvider theResult) {
|
||||
return theResult.getAllResources().stream().map(r -> r.getIdElement().getIdPart()).collect(Collectors.toList());
|
||||
}
|
||||
|
@ -1005,7 +999,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
@Test
|
||||
void secondWordFound() {
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Cloudy, yellow"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Cloudy, yellow"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=yellow");
|
||||
assertThat(resourceIds, hasItem(id1));
|
||||
|
@ -1016,9 +1010,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// smit - matches "smit" and "smith"
|
||||
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=smit");
|
||||
assertThat(resourceIds, hasItems(id1, id2));
|
||||
|
@ -1030,9 +1024,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// smit* - matches "smit" and "smith"
|
||||
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?_elements=valueString&value-string:text=smit*");
|
||||
assertThat(resourceIds, hasItems(id1, id2));
|
||||
|
@ -1044,9 +1038,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// "smit"- matches "smit", but not "smith"
|
||||
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=\"smit\"");
|
||||
assertThat(resourceIds, contains(id2));
|
||||
|
@ -1056,9 +1050,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
@Test
|
||||
void stringTokensAreAnded() {
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Carl Smit"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=car%20smit");
|
||||
assertThat(resourceIds, hasItems(id2));
|
||||
|
@ -1072,9 +1066,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// | Fhir Query String | Executed Query | Matches | No Match
|
||||
// | Smit | Smit* | John Smith | John Smi
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smi"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smi"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=Smit");
|
||||
assertThat(resourceIds, hasItems(id1));
|
||||
|
@ -1085,9 +1079,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// | Fhir Query String | Executed Query | Matches | No Match | Note
|
||||
// | Jo Smit | Jo* Smit* | John Smith | John Frank | Multiple bare terms are `AND`
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "John Frank"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "John Frank"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=Jo%20Smit");
|
||||
assertThat(resourceIds, hasItems(id1));
|
||||
|
@ -1098,9 +1092,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// | Fhir Query String | Executed Query | Matches | No Match | Note
|
||||
// | frank | john | frank | john | Frank Smith | Franklin Smith | SQS characters disable prefix wildcard
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Frank Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Frank Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Franklin Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Franklin Smith"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text=frank|john");
|
||||
assertThat(resourceIds, hasItems(id1));
|
||||
|
@ -1111,9 +1105,9 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
// | Fhir Query String | Executed Query | Matches | No Match | Note
|
||||
// | 'frank' | 'frank' | Frank Smith | Franklin Smith | Quoted terms are exact match
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Frank Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Frank Smith"))).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "Franklin Smith"))).getIdPart();
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "Franklin Smith"))).getIdPart();
|
||||
|
||||
List<String> resourceIds = myTestDaoSearch.searchForIds("/Observation?value-string:text='frank'");
|
||||
assertThat(resourceIds, hasItems(id1));
|
||||
|
@ -1805,10 +1799,10 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
@Test
|
||||
public void byValueString() {
|
||||
String id1 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "a-string-value-1")
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "a-string-value-1")
|
||||
)).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "a-string-value-2")
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "a-string-value-2")
|
||||
)).getIdPart();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
@ -1950,7 +1944,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
myTestDataBuilder.withObservationCode("http://example.com/", "the-code-1")
|
||||
)).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "a-string-value-2")
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "a-string-value-2")
|
||||
)).getIdPart();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
@ -2065,13 +2059,13 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
myTestDataBuilder.withObservationCode("http://example.com/", "the-code-1"),
|
||||
myTestDataBuilder.withEffectiveDate("2017-01-20T03:21:47"),
|
||||
myTestDataBuilder.withTag("http://example.org", "aTag"),
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "a-string-value-1")
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "a-string-value-1")
|
||||
)).getIdPart();
|
||||
String id2 = myTestDataBuilder.createObservation(List.of(
|
||||
myTestDataBuilder.withObservationCode("http://example.com/", "the-code-2"),
|
||||
myTestDataBuilder.withEffectiveDate("2017-01-24T03:21:47"),
|
||||
myTestDataBuilder.withTag("http://example.org", "aTag"),
|
||||
myTestDataBuilder.withPrimitiveAttribute("valueString", "a-string-value-2")
|
||||
myTestDataBuilder.withResourcePrimitiveAttribute("valueString", "a-string-value-2")
|
||||
)).getIdPart();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
|
|
@ -34,16 +34,20 @@ import javax.persistence.ManyToOne;
|
|||
import javax.persistence.MapsId;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable.SOURCE_URI_LENGTH;
|
||||
|
||||
@Table(name = "HFJ_RES_VER_PROV", indexes = {
|
||||
@Index(name = "IDX_RESVERPROV_SOURCEURI", columnList = "SOURCE_URI"),
|
||||
@Index(name = "IDX_RESVERPROV_REQUESTID", columnList = "REQUEST_ID"),
|
||||
//@Index(name = "IDX_RESVERPROV_RESID", columnList = "RES_PID")
|
||||
@Index(name = "IDX_RESVERPROV_RES_PID", columnList = "RES_PID"),
|
||||
@Index(name = "IDX_RESVERPROV_RES_VER_PID", columnList = "RES_VER_PID")
|
||||
}, uniqueConstraints = {
|
||||
})
|
||||
@Entity
|
||||
public class ResourceHistoryProvenanceEntity extends BasePartitionable {
|
||||
|
||||
public static final int SOURCE_URI_LENGTH = 100;
|
||||
|
||||
@Id
|
||||
@Column(name = "RES_VER_PID")
|
||||
|
|
|
@ -25,28 +25,9 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hibernate.annotations.Columns;
|
||||
import org.hibernate.annotations.OptimisticLock;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -61,6 +42,7 @@ import java.util.Collection;
|
|||
})
|
||||
public class ResourceHistoryTable extends BaseHasResource implements Serializable {
|
||||
public static final String IDX_RESVER_ID_VER = "IDX_RESVER_ID_VER";
|
||||
public static final int SOURCE_URI_LENGTH = 100;
|
||||
/**
|
||||
* @see ResourceEncodingEnum
|
||||
*/
|
||||
|
@ -94,13 +76,18 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
@org.hibernate.annotations.Type(type = JpaConstants.ORG_HIBERNATE_TYPE_TEXT_TYPE)
|
||||
@OptimisticLock(excluded = true)
|
||||
private String myResourceTextVc;
|
||||
|
||||
@Column(name = "RES_ENCODING", nullable = false, length = ENCODING_COL_LENGTH)
|
||||
@Enumerated(EnumType.STRING)
|
||||
@OptimisticLock(excluded = true)
|
||||
private ResourceEncodingEnum myEncoding;
|
||||
@OneToOne(mappedBy = "myResourceHistoryTable", cascade = {CascadeType.REMOVE})
|
||||
private ResourceHistoryProvenanceEntity myProvenance;
|
||||
// TODO: This was added in 6.8.0 - In the future we should drop ResourceHistoryProvenanceEntity
|
||||
@Column(name = "SOURCE_URI", length = SOURCE_URI_LENGTH, nullable = true)
|
||||
private String mySourceUri;
|
||||
// TODO: This was added in 6.8.0 - In the future we should drop ResourceHistoryProvenanceEntity
|
||||
@Column(name = "REQUEST_ID", length = Constants.REQUEST_ID_LENGTH, nullable = true)
|
||||
private String myRequestId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -109,6 +96,22 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
super();
|
||||
}
|
||||
|
||||
public String getSourceUri() {
|
||||
return mySourceUri;
|
||||
}
|
||||
|
||||
public void setSourceUri(String theSourceUri) {
|
||||
mySourceUri = theSourceUri;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return myRequestId;
|
||||
}
|
||||
|
||||
public void setRequestId(String theRequestId) {
|
||||
myRequestId = theRequestId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
|
@ -215,6 +218,10 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
return myResourceVersion;
|
||||
}
|
||||
|
||||
public void setVersion(long theVersion) {
|
||||
myResourceVersion = theVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeleted() {
|
||||
return getDeleted() != null;
|
||||
|
@ -225,10 +232,6 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
setDeleted(null);
|
||||
}
|
||||
|
||||
public void setVersion(long theVersion) {
|
||||
myResourceVersion = theVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaPid getPersistentId() {
|
||||
return JpaPid.fromId(myResourceId);
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ConsumeFilesStepR4Test extends BasePartitioningR4Test {
|
|||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void before() throws ServletException {
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myStorageSettings.setInlineResourceTextBelowSize(10000);
|
||||
|
|
|
@ -23,13 +23,11 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
@ -75,8 +73,10 @@ public abstract class BasePartitioningR4Test extends BaseJpaR4SystemTest {
|
|||
myStorageSettings.setMatchUrlCacheEnabled(new JpaStorageSettings().getMatchUrlCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() throws ServletException {
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setIncludePartitionInSearchHashes(new PartitionSettings().isIncludePartitionInSearchHashes());
|
||||
|
||||
|
@ -183,7 +183,7 @@ public abstract class BasePartitioningR4Test extends BaseJpaR4SystemTest {
|
|||
when(mySrd.getRequestId()).thenReturn("REQUEST_ID");
|
||||
}
|
||||
|
||||
protected Consumer<IBaseResource> withPartition(Integer thePartitionId) {
|
||||
protected ICreationArgument withPartition(Integer thePartitionId) {
|
||||
return t -> {
|
||||
if (thePartitionId != null) {
|
||||
addCreatePartition(thePartitionId, null);
|
||||
|
|
|
@ -953,14 +953,14 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
|||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
// NoOp OptimisticLock OptimizeMode ExpectedSelect ExpectedUpdate
|
||||
" false, false, CURRENT_VERSION, 2, 10",
|
||||
" false, false, CURRENT_VERSION, 2, 1",
|
||||
" true, false, CURRENT_VERSION, 2, 0",
|
||||
" false, true, CURRENT_VERSION, 12, 10",
|
||||
" false, true, CURRENT_VERSION, 12, 1",
|
||||
" true, true, CURRENT_VERSION, 12, 0",
|
||||
" false, false, ALL_VERSIONS, 22, 20",
|
||||
" true, false, ALL_VERSIONS, 22, 0",
|
||||
" false, true, ALL_VERSIONS, 32, 20",
|
||||
" true, true, ALL_VERSIONS, 32, 0",
|
||||
" false, false, ALL_VERSIONS, 12, 10",
|
||||
" true, false, ALL_VERSIONS, 12, 0",
|
||||
" false, true, ALL_VERSIONS, 22, 10",
|
||||
" true, true, ALL_VERSIONS, 22, 0",
|
||||
})
|
||||
public void testReindexJob_OptimizeStorage(boolean theNoOp, boolean theOptimisticLock, ReindexParameters.OptimizeStorageModeEnum theOptimizeStorageModeEnum, int theExpectedSelectCount, int theExpectedUpdateCount) {
|
||||
// Setup
|
||||
|
@ -998,7 +998,6 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
|||
RunOutcome outcome = myReindexStep.doReindex(data, mock(IJobDataSink.class), "123", "456", params);
|
||||
|
||||
// validate
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
assertEquals(theExpectedSelectCount, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
assertEquals(theExpectedUpdateCount, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||
assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||
|
|
|
@ -12,7 +12,7 @@ import ca.uhn.fhir.jpa.test.config.TestHSearchAddInConfig;
|
|||
import ca.uhn.fhir.jpa.test.config.TestR4Config;
|
||||
import ca.uhn.fhir.storage.test.BaseDateSearchDaoTests;
|
||||
import ca.uhn.fhir.storage.test.DaoTestDataBuilder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import ca.uhn.fhir.test.utilities.ITestDataBuilder.ICreationArgument;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
@ -30,7 +30,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
|
@ -194,7 +193,7 @@ public class FhirResourceDaoR4StandardQueriesNoFTTest extends BaseJpaTest {
|
|||
}
|
||||
|
||||
@SafeVarargs
|
||||
private IIdType withObservation(Consumer<IBaseResource>... theBuilder) {
|
||||
private IIdType withObservation(ICreationArgument... theBuilder) {
|
||||
myObservationId = myDataBuilder.createObservation(theBuilder);
|
||||
return myObservationId;
|
||||
}
|
||||
|
@ -270,7 +269,7 @@ public class FhirResourceDaoR4StandardQueriesNoFTTest extends BaseJpaTest {
|
|||
IIdType myResourceId;
|
||||
|
||||
private IIdType withRiskAssessmentWithProbabilty(double theValue) {
|
||||
myResourceId = myDataBuilder.createResource("RiskAssessment", myDataBuilder.withPrimitiveAttribute("prediction.probabilityDecimal", theValue));
|
||||
myResourceId = myDataBuilder.createResource("RiskAssessment", myDataBuilder.withResourcePrimitiveAttribute("prediction.probabilityDecimal", theValue));
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.junit.jupiter.api.Test;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -30,7 +29,7 @@ public class PartitioningNonNullDefaultPartitionR4Test extends BasePartitioningR
|
|||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void before() throws ServletException {
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
||||
myPartitionSettings.setDefaultPartitionId(1);
|
||||
|
|
|
@ -201,7 +201,7 @@ public class ThreadSafeResourceDeleterSvcTest extends BaseJpaR4Test {
|
|||
return myOrganizationDao.search(map).size();
|
||||
}
|
||||
|
||||
private IIdType createPatientWithVersion(Consumer<IBaseResource> theWithId) {
|
||||
private IIdType createPatientWithVersion(ICreationArgument theWithId) {
|
||||
Patient patient = new Patient();
|
||||
patient.addName(new HumanName().setFamily("FAMILY"));
|
||||
theWithId.accept(patient);
|
||||
|
|
|
@ -29,11 +29,13 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.Query;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.blankOrNullString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -44,8 +46,6 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
|
||||
public class ReindexJobTest extends BaseJpaR4Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReindexJobTest.class);
|
||||
|
||||
@Autowired
|
||||
private IJobCoordinator myJobCoordinator;
|
||||
|
||||
|
@ -63,6 +63,8 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
public void after() {
|
||||
myInterceptorRegistry.unregisterAllAnonymousInterceptors();
|
||||
myStorageSettings.setInlineResourceTextBelowSize(new JpaStorageSettings().getInlineResourceTextBelowSize());
|
||||
myStorageSettings.setStoreMetaSourceInformation(new JpaStorageSettings().getStoreMetaSourceInformation());
|
||||
myStorageSettings.setPreserveRequestIdInResourceBody(new JpaStorageSettings().isPreserveRequestIdInResourceBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -73,7 +75,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
Patient p = new Patient();
|
||||
p.setId(patientId.toUnqualifiedVersionless());
|
||||
p.setActive(true);
|
||||
p.addIdentifier().setValue("" + i);
|
||||
p.addIdentifier().setValue(String.valueOf(i));
|
||||
myPatientDao.update(p, mySrd);
|
||||
}
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
@ -127,7 +129,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
Patient p = new Patient();
|
||||
p.setId(patientId.toUnqualifiedVersionless());
|
||||
p.setActive(true);
|
||||
p.addIdentifier().setValue("" + i);
|
||||
p.addIdentifier().setValue(String.valueOf(i));
|
||||
myPatientDao.update(p, mySrd);
|
||||
}
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
@ -168,6 +170,66 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptimizeStorage_AllVersions_CopyProvenanceEntityData() {
|
||||
// Setup
|
||||
myStorageSettings.setStoreMetaSourceInformation(JpaStorageSettings.StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID);
|
||||
myStorageSettings.setPreserveRequestIdInResourceBody(true);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Patient p = new Patient();
|
||||
p.setId("PATIENT" + i);
|
||||
p.getMeta().setSource("http://foo#bar");
|
||||
p.addIdentifier().setValue(String.valueOf(i));
|
||||
myPatientDao.update(p, mySrd);
|
||||
|
||||
p.addIdentifier().setSystem("http://blah");
|
||||
myPatientDao.update(p, mySrd);
|
||||
}
|
||||
|
||||
runInTransaction(()->{
|
||||
assertEquals(20, myResourceHistoryTableDao.count());
|
||||
assertEquals(20, myResourceHistoryProvenanceDao.count());
|
||||
Query query = myEntityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " p SET p.mySourceUri = NULL, p.myRequestId = NULL");
|
||||
assertEquals(20, query.executeUpdate());
|
||||
});
|
||||
|
||||
runInTransaction(()-> {
|
||||
for (var next : myResourceHistoryProvenanceDao.findAll()) {
|
||||
assertEquals("bar", next.getRequestId());
|
||||
assertEquals("http://foo", next.getSourceUri());
|
||||
}
|
||||
for (var next : myResourceHistoryTableDao.findAll()) {
|
||||
assertThat(next.getRequestId(), blankOrNullString());
|
||||
assertThat(next.getSourceUri(), blankOrNullString());
|
||||
}
|
||||
});
|
||||
|
||||
// execute
|
||||
JobInstanceStartRequest startRequest = new JobInstanceStartRequest();
|
||||
startRequest.setJobDefinitionId(ReindexAppCtx.JOB_REINDEX);
|
||||
startRequest.setParameters(
|
||||
new ReindexJobParameters()
|
||||
.setOptimizeStorage(ReindexParameters.OptimizeStorageModeEnum.ALL_VERSIONS)
|
||||
.setReindexSearchParameters(ReindexParameters.ReindexSearchParametersEnum.NONE)
|
||||
);
|
||||
Batch2JobStartResponse startResponse = myJobCoordinator.startInstance(startRequest);
|
||||
myBatch2JobHelper.awaitJobCompletion(startResponse);
|
||||
|
||||
// validate
|
||||
runInTransaction(()-> {
|
||||
for (var next : myResourceHistoryProvenanceDao.findAll()) {
|
||||
assertEquals("bar", next.getRequestId());
|
||||
assertEquals("http://foo", next.getSourceUri());
|
||||
}
|
||||
for (var next : myResourceHistoryTableDao.findAll()) {
|
||||
assertEquals("bar", next.getRequestId());
|
||||
assertEquals("http://foo", next.getSourceUri());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptimizeStorage_DeletedRecords() {
|
||||
// Setup
|
||||
|
@ -214,7 +276,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
|
||||
myReindexTestHelper.createAlleleSearchParameter();
|
||||
|
||||
assertEquals(2, myObservationDao.search(SearchParameterMap.newSynchronous()).size());
|
||||
assertEquals(2, myObservationDao.search(SearchParameterMap.newSynchronous(), mySrd).size());
|
||||
// The search param value is on the observation, but it hasn't been indexed yet
|
||||
assertThat(myReindexTestHelper.getAlleleObservationIds(), hasSize(0));
|
||||
|
||||
|
@ -230,7 +292,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
myBatch2JobHelper.awaitJobCompletion(res);
|
||||
|
||||
// validate
|
||||
assertEquals(2, myObservationDao.search(SearchParameterMap.newSynchronous()).size());
|
||||
assertEquals(2, myObservationDao.search(SearchParameterMap.newSynchronous(), mySrd).size());
|
||||
|
||||
// Now one of them should be indexed
|
||||
List<String> alleleObservationIds = myReindexTestHelper.getAlleleObservationIds();
|
||||
|
@ -249,7 +311,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
assertThat(entriesInSpIndexTokenTable, equalTo(1));
|
||||
|
||||
// simulate resource deletion
|
||||
ResourceTable resource = myResourceTableDao.findById(obsId.getIdPartAsLong()).get();
|
||||
ResourceTable resource = myResourceTableDao.findById(obsId.getIdPartAsLong()).orElseThrow();
|
||||
Date currentDate = new Date();
|
||||
resource.setDeleted(currentDate);
|
||||
resource.setUpdated(currentDate);
|
||||
|
@ -288,7 +350,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
myReindexTestHelper.createAlleleSearchParameter();
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
assertEquals(50, myObservationDao.search(SearchParameterMap.newSynchronous()).size());
|
||||
assertEquals(50, myObservationDao.search(SearchParameterMap.newSynchronous(), mySrd).size());
|
||||
// The search param value is on the observation, but it hasn't been indexed yet
|
||||
assertThat(myReindexTestHelper.getAlleleObservationIds(), hasSize(0));
|
||||
|
||||
|
@ -300,7 +362,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
myBatch2JobHelper.awaitJobCompletion(startResponse);
|
||||
|
||||
// validate
|
||||
assertEquals(50, myObservationDao.search(SearchParameterMap.newSynchronous()).size());
|
||||
assertEquals(50, myObservationDao.search(SearchParameterMap.newSynchronous(), mySrd).size());
|
||||
// Now all of them should be indexed
|
||||
assertThat(myReindexTestHelper.getAlleleObservationIds(), hasSize(50));
|
||||
}
|
||||
|
@ -331,7 +393,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
|
|||
// Verify
|
||||
|
||||
assertEquals(StatusEnum.COMPLETED, outcome.getStatus());
|
||||
assertEquals(null, outcome.getErrorMessage());
|
||||
assertNull(outcome.getErrorMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -283,7 +283,7 @@ public class PartitioningInterceptorR4Test extends BaseJpaR4SystemTest {
|
|||
when(mySrd.getRequestId()).thenReturn("REQUEST_ID");
|
||||
}
|
||||
|
||||
private Consumer<IBaseResource> withPartition(Integer thePartitionId) {
|
||||
private ICreationArgument withPartition(Integer thePartitionId) {
|
||||
return t -> {
|
||||
if (thePartitionId != null) {
|
||||
addCreatePartition(thePartitionId, null);
|
||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
|
|||
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
|
@ -142,7 +143,7 @@ public class AuthorizationInterceptorMultitenantJpaR4Test extends BaseMultitenan
|
|||
Bundle output = myClient
|
||||
.search()
|
||||
.forResource("Observation")
|
||||
.include(Observation.INCLUDE_ALL)
|
||||
.include(IBaseResource.INCLUDE_ALL)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
assertEquals(2, output.getEntry().size());
|
||||
|
@ -165,7 +166,7 @@ public class AuthorizationInterceptorMultitenantJpaR4Test extends BaseMultitenan
|
|||
myClient
|
||||
.search()
|
||||
.forResource("Observation")
|
||||
.include(Observation.INCLUDE_ALL)
|
||||
.include(IBaseResource.INCLUDE_ALL)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
fail();
|
||||
|
@ -198,7 +199,7 @@ public class AuthorizationInterceptorMultitenantJpaR4Test extends BaseMultitenan
|
|||
Bundle bundle = myClient
|
||||
.search()
|
||||
.forResource("Observation")
|
||||
.include(Observation.INCLUDE_ALL)
|
||||
.include(IBaseResource.INCLUDE_ALL)
|
||||
.sort().ascending(Observation.IDENTIFIER)
|
||||
.returnBundle(Bundle.class)
|
||||
.count(3)
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.DEFAULT_PARTITION_NAME;
|
||||
|
@ -124,7 +123,7 @@ public abstract class BaseMultitenantResourceProviderR4Test extends BaseResource
|
|||
|
||||
|
||||
|
||||
protected Consumer<IBaseResource> withTenant(String theTenantId) {
|
||||
protected ICreationArgument withTenant(String theTenantId) {
|
||||
return t -> myTenantClientInterceptor.setTenantId(theTenantId);
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ public class GiantTransactionPerfTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Slice<ResourceHistoryTable> findForResourceIdAndReturnEntities(Pageable thePage, Long theId, Long theDontWantVersion) {
|
||||
public Slice<ResourceHistoryTable> findForResourceIdAndReturnEntitiesAndFetchProvenance(Pageable thePage, Long theId, Long theDontWantVersion) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -383,11 +383,6 @@ public class GiantTransactionPerfTest {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceTextVcForVersion(Long id, String resourceText) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVersion(long theId, long theOldVersion, long theNewVersion) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -28,7 +28,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@SuppressWarnings({"unchecked", "SqlDialectInspection"})
|
||||
@SuppressWarnings({"SqlDialectInspection"})
|
||||
public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
||||
|
||||
@Autowired
|
||||
|
@ -125,7 +125,7 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
|
||||
@Test
|
||||
public void testDryRunTypes_Number() {
|
||||
IIdType id = createResource("ResearchStudy", withPrimitiveAttribute("recruitment.targetNumber", "3"));
|
||||
IIdType id = createResource("ResearchStudy", withResourcePrimitiveAttribute("recruitment.targetNumber", "3"));
|
||||
|
||||
logAllNumberIndexes();
|
||||
|
||||
|
@ -269,7 +269,7 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
|
||||
@Test
|
||||
public void testDryRunTypes_Uri() {
|
||||
IIdType id = createResource("CodeSystem", withPrimitiveAttribute("url", "http://foo"));
|
||||
IIdType id = createResource("CodeSystem", withResourcePrimitiveAttribute("url", "http://foo"));
|
||||
|
||||
Parameters outcome = (Parameters) mySvc.reindexDryRun(new SystemRequestDetails(), id, null);
|
||||
ourLog.info("Output:{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
|
|
|
@ -42,6 +42,7 @@ import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
|||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkJpaRepository;
|
||||
import ca.uhn.fhir.jpa.dao.data.IPartitionDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryProvenanceDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
|
@ -418,6 +419,8 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
|
|||
@Autowired
|
||||
protected IResourceHistoryTableDao myResourceHistoryTableDao;
|
||||
@Autowired
|
||||
protected IResourceHistoryProvenanceDao myResourceHistoryProvenanceDao;
|
||||
@Autowired
|
||||
protected IForcedIdDao myForcedIdDao;
|
||||
@Autowired
|
||||
@Qualifier("myCoverageDaoR4")
|
||||
|
|
|
@ -113,8 +113,8 @@ public class CommonConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public IBalpAuditEventSink balpAuditEventSink(FhirContext theFhirContext) {
|
||||
return new AsyncMemoryQueueBackedFhirClientBalpSink(theFhirContext, "http://localhost:8000/baseAudit");
|
||||
public IBalpAuditEventSink balpAuditEventSink() {
|
||||
return new AsyncMemoryQueueBackedFhirClientBalpSink(FhirContext.forR4Cached(), "http://localhost:8000/baseAudit");
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -95,7 +95,7 @@ public class AsyncMemoryQueueBackedFhirClientBalpSink extends FhirClientBalpSink
|
|||
*/
|
||||
public AsyncMemoryQueueBackedFhirClientBalpSink(IGenericClient theClient) {
|
||||
super(theClient);
|
||||
myThreadPool = ThreadPoolUtil.newThreadPool(1, 1, "BalpClientSink-" + ourNextThreadId.getAndIncrement() + "-", 100);
|
||||
myThreadPool = ThreadPoolUtil.newThreadPool(1, 1, "BalpClientSink-" + ourNextThreadId.getAndIncrement() + "-", Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,12 +26,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.MetaUtil;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.ICompositeType;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.InstantType;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -54,21 +49,33 @@ import static org.hamcrest.Matchers.matchesPattern;
|
|||
public interface ITestDataBuilder {
|
||||
Logger ourLog = LoggerFactory.getLogger(ITestDataBuilder.class);
|
||||
|
||||
/**
|
||||
* Name chosen to avoid potential for conflict. This is an internal API to this interface.
|
||||
*/
|
||||
static void __setPrimitiveChild(FhirContext theFhirContext, IBase theTarget, String theElementName, String theElementType, String theValue) {
|
||||
BaseRuntimeElementCompositeDefinition def = (BaseRuntimeElementCompositeDefinition) theFhirContext.getElementDefinition(theTarget.getClass());
|
||||
BaseRuntimeChildDefinition activeChild = def.getChildByName(theElementName);
|
||||
|
||||
IPrimitiveType<?> booleanType = (IPrimitiveType<?>) activeChild.getChildByName(theElementName).newInstance();
|
||||
booleanType.setValueAsString(theValue);
|
||||
activeChild.getMutator().addValue(theTarget, booleanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Patient.active = true
|
||||
*/
|
||||
default Consumer<IBaseResource> withActiveTrue() {
|
||||
default ICreationArgument withActiveTrue() {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "active", "boolean", "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Patient.active = false
|
||||
*/
|
||||
default Consumer<IBaseResource> withActiveFalse() {
|
||||
default ICreationArgument withActiveFalse() {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "active", "boolean", "false");
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withFamily(String theFamily) {
|
||||
default ICreationArgument withFamily(String theFamily) {
|
||||
return t -> {
|
||||
IPrimitiveType<?> family = (IPrimitiveType<?>) getFhirContext().getElementDefinition("string").newInstance();
|
||||
family.setValueAsString(theFamily);
|
||||
|
@ -77,50 +84,50 @@ public interface ITestDataBuilder {
|
|||
ICompositeType humanName = (ICompositeType) humanNameDef.newInstance();
|
||||
humanNameDef.getChildByName("family").getMutator().addValue(humanName, family);
|
||||
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
||||
BaseRuntimeElementCompositeDefinition resourceDef = (BaseRuntimeElementCompositeDefinition) getFhirContext().getElementDefinition(t.getClass());
|
||||
resourceDef.getChildByName("name").getMutator().addValue(t, humanName);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/** Patient.name.given */
|
||||
default <T extends IBaseResource> Consumer<T> withGiven(String theName) {
|
||||
return withPrimitiveAttribute("name.given", theName);
|
||||
/**
|
||||
* Patient.name.given
|
||||
*/
|
||||
default ICreationArgument withGiven(String theName) {
|
||||
return withResourcePrimitiveAttribute("name.given", theName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set Patient.birthdate
|
||||
*/
|
||||
default Consumer<IBaseResource> withBirthdate(String theBirthdate) {
|
||||
default ICreationArgument withBirthdate(String theBirthdate) {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "birthDate", "dateTime", theBirthdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Observation.status
|
||||
*/
|
||||
default Consumer<IBaseResource> withStatus(String theStatus) {
|
||||
default ICreationArgument withStatus(String theStatus) {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "status", "code", theStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Observation.effectiveDate
|
||||
*/
|
||||
default Consumer<IBaseResource> withEffectiveDate(String theDate) {
|
||||
default ICreationArgument withEffectiveDate(String theDate) {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "effectiveDateTime", "dateTime", theDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Observation.effectiveDate
|
||||
*/
|
||||
default Consumer<IBaseResource> withDateTimeAt(String thePath, String theDate) {
|
||||
default ICreationArgument withDateTimeAt(String thePath, String theDate) {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, thePath, "dateTime", theDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [Resource].identifier.system and [Resource].identifier.value
|
||||
*/
|
||||
default Consumer<IBaseResource> withIdentifier(String theSystem, String theValue) {
|
||||
default ICreationArgument withIdentifier(String theSystem, String theValue) {
|
||||
return t -> {
|
||||
IPrimitiveType<?> system = (IPrimitiveType<?>) getFhirContext().getElementDefinition("uri").newInstance();
|
||||
system.setValueAsString(theSystem);
|
||||
|
@ -133,7 +140,7 @@ public interface ITestDataBuilder {
|
|||
identifierDef.getChildByName("system").getMutator().addValue(identifier, system);
|
||||
identifierDef.getChildByName("value").getMutator().addValue(identifier, value);
|
||||
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition((Class<? extends IBaseResource>) t.getClass());
|
||||
resourceDef.getChildByName("identifier").getMutator().addValue(t, identifier);
|
||||
};
|
||||
}
|
||||
|
@ -141,73 +148,74 @@ public interface ITestDataBuilder {
|
|||
/**
|
||||
* Set Organization.name
|
||||
*/
|
||||
default Consumer<IBaseResource> withName(String theStatus) {
|
||||
default ICreationArgument withName(String theStatus) {
|
||||
return t -> __setPrimitiveChild(getFhirContext(), t, "name", "string", theStatus);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withId(String theId) {
|
||||
default ICreationArgument withId(String theId) {
|
||||
return t -> {
|
||||
assertThat(theId, matchesPattern("[a-zA-Z0-9-]+"));
|
||||
t.setId(theId);
|
||||
((IBaseResource)t).setId(theId);
|
||||
};
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withId(IIdType theId) {
|
||||
return t -> t.setId(theId.toUnqualifiedVersionless());
|
||||
default ICreationArgument withId(IIdType theId) {
|
||||
return t -> ((IBaseResource)t).setId(theId.toUnqualifiedVersionless());
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withTag(String theSystem, String theCode) {
|
||||
return t -> t.getMeta().addTag().setSystem(theSystem).setCode(theCode);
|
||||
default ICreationArgument withTag(String theSystem, String theCode) {
|
||||
return t -> ((IBaseResource)t).getMeta().addTag().setSystem(theSystem).setCode(theCode);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withSecurity(String theSystem, String theCode) {
|
||||
return t -> t.getMeta().addSecurity().setSystem(theSystem).setCode(theCode);
|
||||
default ICreationArgument withSecurity(String theSystem, String theCode) {
|
||||
return t -> ((IBaseResource)t).getMeta().addSecurity().setSystem(theSystem).setCode(theCode);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withProfile(String theProfile) {
|
||||
return t -> t.getMeta().addProfile(theProfile);
|
||||
default ICreationArgument withProfile(String theProfile) {
|
||||
return t -> ((IBaseResource)t).getMeta().addProfile(theProfile);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withSource(FhirContext theContext, String theSource) {
|
||||
return t -> MetaUtil.setSource(theContext, t.getMeta(), theSource);
|
||||
default ICreationArgument withSource(FhirContext theContext, String theSource) {
|
||||
return t -> MetaUtil.setSource(theContext, ((IBaseResource)t).getMeta(), theSource);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withLastUpdated(Date theLastUpdated) {
|
||||
return t -> t.getMeta().setLastUpdated(theLastUpdated);
|
||||
default ICreationArgument withLastUpdated(Date theLastUpdated) {
|
||||
return t -> ((IBaseResource)t).getMeta().setLastUpdated(theLastUpdated);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withLastUpdated(String theIsoDate) {
|
||||
return t -> t.getMeta().setLastUpdated(new InstantType(theIsoDate).getValue());
|
||||
default ICreationArgument withLastUpdated(String theIsoDate) {
|
||||
return t -> ((IBaseResource)t).getMeta().setLastUpdated(new InstantType(theIsoDate).getValue());
|
||||
}
|
||||
|
||||
default IIdType createEncounter(Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createEncounter(ICreationArgument... theModifiers) {
|
||||
return createResource("Encounter", theModifiers);
|
||||
}
|
||||
|
||||
default IIdType createGroup(Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createGroup(ICreationArgument... theModifiers) {
|
||||
return createResource("Group", theModifiers);
|
||||
}
|
||||
|
||||
default IIdType createObservation(Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createObservation(ICreationArgument... theModifiers) {
|
||||
return createResource("Observation", theModifiers);
|
||||
}
|
||||
|
||||
default IIdType createObservation(Collection<Consumer<IBaseResource>> theModifiers) {
|
||||
return createResource("Observation", theModifiers.toArray(new Consumer[0]));
|
||||
default IIdType createObservation(Collection<ICreationArgument> theModifiers) {
|
||||
return createResource("Observation", theModifiers.toArray(new ICreationArgument[0]));
|
||||
}
|
||||
|
||||
default IBaseResource buildPatient(Consumer<IBaseResource>... theModifiers) {
|
||||
default IBaseResource buildPatient(ICreationArgument... theModifiers) {
|
||||
return buildResource("Patient", theModifiers);
|
||||
}
|
||||
default IIdType createPatient(Consumer<IBaseResource>... theModifiers) {
|
||||
|
||||
default IIdType createPatient(ICreationArgument... theModifiers) {
|
||||
return createResource("Patient", theModifiers);
|
||||
}
|
||||
|
||||
default IIdType createOrganization(Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createOrganization(ICreationArgument... theModifiers) {
|
||||
return createResource("Organization", theModifiers);
|
||||
}
|
||||
|
||||
default IIdType createResource(String theResourceType, Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createResource(String theResourceType, ICreationArgument... theModifiers) {
|
||||
IBaseResource resource = buildResource(theResourceType, theModifiers);
|
||||
|
||||
if (ourLog.isDebugEnabled()) {
|
||||
|
@ -221,7 +229,7 @@ public interface ITestDataBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
default IIdType createResourceFromJson(String theJson, Consumer<IBaseResource>... theModifiers) {
|
||||
default IIdType createResourceFromJson(String theJson, ICreationArgument... theModifiers) {
|
||||
IBaseResource resource = getFhirContext().newJsonParser().parseResource(theJson);
|
||||
applyElementModifiers(resource, theModifiers);
|
||||
|
||||
|
@ -236,70 +244,76 @@ public interface ITestDataBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
default <T extends IBaseResource> T buildResource(String theResourceType, Consumer<IBaseResource>... theModifiers) {
|
||||
default <T extends IBaseResource> T buildResource(String theResourceType, ICreationArgument... theModifiers) {
|
||||
IBaseResource resource = getFhirContext().getResourceDefinition(theResourceType).newInstance();
|
||||
applyElementModifiers(resource, theModifiers);
|
||||
return (T) resource;
|
||||
}
|
||||
|
||||
|
||||
default Consumer<IBaseResource> withSubject(@Nullable IIdType theSubject) {
|
||||
default ICreationArgument withSubject(@Nullable IIdType theSubject) {
|
||||
return withReference("subject", theSubject);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withSubject(@Nullable String theSubject) {
|
||||
default ICreationArgument withSubject(@Nullable String theSubject) {
|
||||
return withSubject(new IdType(theSubject));
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withPatient(@Nullable IIdType theSubject) {
|
||||
default ICreationArgument withPatient(@Nullable IIdType theSubject) {
|
||||
return withReference("patient", theSubject);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withPatient(@Nullable String theSubject) {
|
||||
default ICreationArgument withPatient(@Nullable String theSubject) {
|
||||
return withSubject(new IdType(theSubject));
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withGroupMember(@Nullable IIdType theMember) {
|
||||
return withPrimitiveAttribute("member.entity.reference", theMember);
|
||||
default ICreationArgument withGroupMember(@Nullable IIdType theMember) {
|
||||
return withResourcePrimitiveAttribute("member.entity.reference", theMember);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withGroupMember(@Nullable String theMember) {
|
||||
default ICreationArgument withGroupMember(@Nullable String theMember) {
|
||||
return withGroupMember(new IdType(theMember));
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withEncounter(@Nullable String theEncounter) {
|
||||
default ICreationArgument withEncounter(@Nullable String theEncounter) {
|
||||
return withReference("encounter", new IdType(theEncounter));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Consumer<IBaseResource> withReference(String theReferenceName, @Nullable IIdType theReferenceValue) {
|
||||
private ICreationArgument withReference(String theReferenceName, @Nullable IIdType theReferenceValue) {
|
||||
return t -> {
|
||||
if (theReferenceValue != null && theReferenceValue.getValue() != null) {
|
||||
IBaseReference reference = (IBaseReference) getFhirContext().getElementDefinition("Reference").newInstance();
|
||||
reference.setReference(theReferenceValue.getValue());
|
||||
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t);
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition((IBaseResource) t);
|
||||
resourceDef.getChildByName(theReferenceName).getMutator().addValue(t, reference);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
default <T extends IBase> Consumer<T> withPrimitiveAttribute(String thePath, Object theValue) {
|
||||
return t->{
|
||||
default Consumer<IBase> withPrimitiveAttribute(String thePath, Object theValue) {
|
||||
return t -> {
|
||||
FhirTerser terser = getFhirContext().newTerser();
|
||||
terser.addElement(t, thePath, ""+theValue);
|
||||
terser.addElement(t, thePath, "" + theValue);
|
||||
};
|
||||
}
|
||||
|
||||
default <T extends IBase, E extends IBase> Consumer<T> withElementAt(String thePath, Consumer<E>... theModifiers) {
|
||||
return t->{
|
||||
default ICreationArgument withResourcePrimitiveAttribute(String thePath, Object theValue) {
|
||||
return t -> {
|
||||
FhirTerser terser = getFhirContext().newTerser();
|
||||
terser.addElement(t, thePath, "" + theValue);
|
||||
};
|
||||
}
|
||||
|
||||
default <E extends IBase> ICreationArgument withElementAt(String thePath, Consumer<E>... theModifiers) {
|
||||
return t -> {
|
||||
FhirTerser terser = getFhirContext().newTerser();
|
||||
E element = terser.addElement(t, thePath);
|
||||
applyElementModifiers(element, theModifiers);
|
||||
};
|
||||
}
|
||||
|
||||
default <T extends IBase> Consumer<T> withQuantityAtPath(String thePath, Number theValue, String theSystem, String theCode) {
|
||||
default ICreationArgument withQuantityAtPath(String thePath, Number theValue, String theSystem, String theCode) {
|
||||
return withElementAt(thePath,
|
||||
withPrimitiveAttribute("value", theValue),
|
||||
withPrimitiveAttribute("system", theSystem),
|
||||
|
@ -307,11 +321,11 @@ public interface ITestDataBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an Element and apply modifiers
|
||||
*
|
||||
* @param theElementType the FHIR Element type to create
|
||||
* @param theModifiers modifiers to apply after construction
|
||||
* @param theModifiers modifiers to apply after construction
|
||||
* @return the Element
|
||||
*/
|
||||
default IBase withElementOfType(String theElementType, Consumer<IBase>... theModifiers) {
|
||||
|
@ -326,19 +340,19 @@ public interface ITestDataBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withObservationCode(@Nullable String theSystem, @Nullable String theCode) {
|
||||
default ICreationArgument withObservationCode(@Nullable String theSystem, @Nullable String theCode) {
|
||||
return withObservationCode(theSystem, theCode, null);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withObservationCode(@Nullable String theSystem, @Nullable String theCode, @Nullable String theDisplay) {
|
||||
default ICreationArgument withObservationCode(@Nullable String theSystem, @Nullable String theCode, @Nullable String theDisplay) {
|
||||
return withCodingAt("code.coding", theSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
default <T extends IBase> Consumer<T> withCodingAt(String thePath, @Nullable String theSystem, @Nullable String theValue) {
|
||||
default <T extends IBase> ICreationArgument withCodingAt(String thePath, @Nullable String theSystem, @Nullable String theValue) {
|
||||
return withCodingAt(thePath, theSystem, theValue, null);
|
||||
}
|
||||
|
||||
default <T extends IBase> Consumer<T> withCodingAt(String thePath, @Nullable String theSystem, @Nullable String theValue, @Nullable String theDisplay) {
|
||||
default <T extends IBase> ICreationArgument withCodingAt(String thePath, @Nullable String theSystem, @Nullable String theValue, @Nullable String theDisplay) {
|
||||
return withElementAt(thePath,
|
||||
withPrimitiveAttribute("system", theSystem),
|
||||
withPrimitiveAttribute("code", theValue),
|
||||
|
@ -346,15 +360,15 @@ public interface ITestDataBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
default <T extends IBaseResource, E extends IBase> Consumer<T> withObservationComponent(Consumer<E>... theModifiers) {
|
||||
default ICreationArgument withObservationComponent(ICreationArgument... theModifiers) {
|
||||
return withElementAt("component", theModifiers);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withObservationHasMember(@Nullable IIdType theHasMember) {
|
||||
default ICreationArgument withObservationHasMember(@Nullable IIdType theHasMember) {
|
||||
return withReference("hasMember", theHasMember);
|
||||
}
|
||||
|
||||
default Consumer<IBaseResource> withOrganization(@Nullable IIdType theHasMember) {
|
||||
default ICreationArgument withOrganization(@Nullable IIdType theHasMember) {
|
||||
return withReference("managingOrganization", theHasMember);
|
||||
}
|
||||
|
||||
|
@ -373,21 +387,15 @@ public interface ITestDataBuilder {
|
|||
*/
|
||||
FhirContext getFhirContext();
|
||||
|
||||
/**
|
||||
* Name chosen to avoid potential for conflict. This is an internal API to this interface.
|
||||
*/
|
||||
static void __setPrimitiveChild(FhirContext theFhirContext, IBaseResource theTarget, String theElementName, String theElementType, String theValue) {
|
||||
RuntimeResourceDefinition def = theFhirContext.getResourceDefinition(theTarget.getClass());
|
||||
BaseRuntimeChildDefinition activeChild = def.getChildByName(theElementName);
|
||||
|
||||
IPrimitiveType<?> booleanType = (IPrimitiveType<?>) activeChild.getChildByName(theElementName).newInstance();
|
||||
booleanType.setValueAsString(theValue);
|
||||
activeChild.getMutator().addValue(theTarget, booleanType);
|
||||
default ICreationArgument[] asArray(ICreationArgument theIBaseResourceConsumer) {
|
||||
return new ICreationArgument[]{theIBaseResourceConsumer};
|
||||
}
|
||||
|
||||
interface Support {
|
||||
FhirContext getFhirContext();
|
||||
|
||||
IIdType doCreateResource(IBaseResource theResource);
|
||||
|
||||
IIdType doUpdateResource(IBaseResource theResource);
|
||||
}
|
||||
|
||||
|
@ -411,6 +419,10 @@ public interface ITestDataBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
interface ICreationArgument extends Consumer<IBase> {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy support to use ITestDataBuilder as just a builder, not a DAO
|
||||
*/
|
||||
|
@ -438,4 +450,6 @@ public interface ITestDataBuilder {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue