Reduce SQL queries for _include (#4007)
* Rework includes processing for reuse * Optimize include * Test fixes * Bump version down * Fixed * Update * Test fixes * Start to add javadoc * Test fixes
This commit is contained in:
parent
3935b78083
commit
3bab3544ec
|
@ -276,20 +276,6 @@ public class RuntimeSearchParam {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean pathMatchesResourceType(String theResourceName, String thePath) {
|
|
||||||
if (thePath.startsWith(theResourceName + ".")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (thePath.startsWith("Resouce.") || thePath.startsWith("DomainResource.")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Character.isLowerCase(thePath.charAt(0))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum RuntimeSearchParamStatusEnum {
|
public enum RuntimeSearchParamStatusEnum {
|
||||||
ACTIVE,
|
ACTIVE,
|
||||||
DRAFT,
|
DRAFT,
|
||||||
|
@ -297,6 +283,51 @@ public class RuntimeSearchParam {
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method tests whether a given FHIRPath expression <i>could</i>
|
||||||
|
* possibly apply to the given resource type.
|
||||||
|
*
|
||||||
|
* @param theResourceName
|
||||||
|
* @param thePath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static boolean pathMatchesResourceType(String theResourceName, String thePath) {
|
||||||
|
for (int i = 0; i < thePath.length() - 1; i++) {
|
||||||
|
char nextChar = thePath.charAt(i);
|
||||||
|
if (Character.isLowerCase(nextChar)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Character.isLetter(nextChar)) {
|
||||||
|
if (fhirPathExpressionStartsWith(theResourceName, thePath, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fhirPathExpressionStartsWith("Resource", thePath, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fhirPathExpressionStartsWith("DomainResource", thePath, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean fhirPathExpressionStartsWith(String theResourceName, String thePath, int theStartingIndex) {
|
||||||
|
if (thePath.startsWith(theResourceName, theStartingIndex) && thePath.length() > theResourceName.length()) {
|
||||||
|
for (int i = theResourceName.length() + theStartingIndex; i < thePath.length(); i++) {
|
||||||
|
char nextChar = thePath.charAt(i);
|
||||||
|
if (nextChar == '.') {
|
||||||
|
return true;
|
||||||
|
} else if (nextChar != ' ') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Component {
|
public static class Component {
|
||||||
private final String myExpression;
|
private final String myExpression;
|
||||||
private final String myReference;
|
private final String myReference;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ca.uhn.fhir.context;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class RuntimeSearchParamTest {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"true, Patient, Patient.identifier",
|
||||||
|
"true, Patient, Resource.identifier",
|
||||||
|
"true, Patient, DomainResource.identifier",
|
||||||
|
"true, Patient, (Patient.identifier)",
|
||||||
|
"true, Patient, (Patient.identifier )",
|
||||||
|
"true, Patient, (Resource.identifier)",
|
||||||
|
"true, Patient, (DomainResource.identifier)",
|
||||||
|
"true, Patient, (DomainResource.identifier )",
|
||||||
|
"true, Patient, ((Patient.identifier))",
|
||||||
|
"true, Patient, ((Patient.identifier ))",
|
||||||
|
"true, Patient, ((Patient.identifier ) )",
|
||||||
|
"true, Patient, (( Patient.identifier))",
|
||||||
|
"true, Patient, ( ( Patient.identifier))",
|
||||||
|
"true, Patient, ((Resource.identifier))",
|
||||||
|
"true, Patient, (( Resource.identifier))",
|
||||||
|
"true, Patient, (( Resource.identifier))",
|
||||||
|
"true, Patient, ((DomainResource.identifier))",
|
||||||
|
"true, Patient, (( DomainResource.identifier))",
|
||||||
|
"true, Patient, (( DomainResource. identifier))",
|
||||||
|
"true, Patient, (( DomainResource . identifier))",
|
||||||
|
"true, Patient, (( DomainResource.identifier))",
|
||||||
|
|
||||||
|
"true, Patient, identifier",
|
||||||
|
"true, Patient, (identifier)",
|
||||||
|
|
||||||
|
"false, Patient, Observation.identifier",
|
||||||
|
"false, Patient, PatientFoo.identifier",
|
||||||
|
"false, Patient, Patient",
|
||||||
|
"false, Patient, PatientFoo",
|
||||||
|
"false, Patient, ((Observation.identifier)",
|
||||||
|
"false, Patient, ((Observation.identifier))",
|
||||||
|
"false, Patient, (( Observation.identifier))",
|
||||||
|
"false, Patient, (( Observation.identifier))"
|
||||||
|
})
|
||||||
|
public void getPathMatchesResourceType(boolean theShouldMatch, String theResourceType, String thePath) {
|
||||||
|
assertEquals(theShouldMatch, RuntimeSearchParam.pathMatchesResourceType(theResourceType, thePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: perf
|
||||||
|
issue: 4007
|
||||||
|
title: "Processing for `_include` and `_revinclude` parameters in the JPA server has been streamlined, which should
|
||||||
|
improve performance on systems where includes are heavily used."
|
||||||
|
|
|
@ -43,7 +43,7 @@ public interface ISearchDao extends JpaRepository<Search, Long>, IHapiFhirJpaRep
|
||||||
@Query("SELECT s.myId FROM Search s WHERE s.myDeleted = TRUE")
|
@Query("SELECT s.myId FROM Search s WHERE s.myDeleted = TRUE")
|
||||||
Slice<Long> findDeleted(Pageable thePage);
|
Slice<Long> findDeleted(Pageable thePage);
|
||||||
|
|
||||||
@Query("SELECT s FROM Search s WHERE s.myResourceType = :type AND mySearchQueryStringHash = :hash AND (s.myCreated > :cutoff) AND s.myDeleted = FALSE AND s.myStatus <> 'FAILED'")
|
@Query("SELECT s FROM Search s WHERE s.myResourceType = :type AND s.mySearchQueryStringHash = :hash AND (s.myCreated > :cutoff) AND s.myDeleted = FALSE AND s.myStatus <> 'FAILED'")
|
||||||
Collection<Search> findWithCutoffOrExpiry(@Param("type") String theResourceType, @Param("hash") int theHashCode, @Param("cutoff") Date theCreatedCutoff);
|
Collection<Search> findWithCutoffOrExpiry(@Param("type") String theResourceType, @Param("hash") int theHashCode, @Param("cutoff") Date theCreatedCutoff);
|
||||||
|
|
||||||
@Query("SELECT COUNT(s) FROM Search s WHERE s.myDeleted = TRUE")
|
@Query("SELECT COUNT(s) FROM Search s WHERE s.myDeleted = TRUE")
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
|
@ -99,7 +100,7 @@ public class Search implements ICachedSearchDetails, Serializable {
|
||||||
@SequenceGenerator(name = "SEQ_SEARCH", sequenceName = "SEQ_SEARCH")
|
@SequenceGenerator(name = "SEQ_SEARCH", sequenceName = "SEQ_SEARCH")
|
||||||
@Column(name = "PID")
|
@Column(name = "PID")
|
||||||
private Long myId;
|
private Long myId;
|
||||||
@OneToMany(mappedBy = "mySearch")
|
@OneToMany(mappedBy = "mySearch", cascade = CascadeType.ALL)
|
||||||
private Collection<SearchInclude> myIncludes;
|
private Collection<SearchInclude> myIncludes;
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
@Column(name = "LAST_UPDATED_HIGH", nullable = true, insertable = true, updatable = false)
|
@Column(name = "LAST_UPDATED_HIGH", nullable = true, insertable = true, updatable = false)
|
||||||
|
|
|
@ -1027,7 +1027,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
* so it can't be Collections.emptySet() or some such thing
|
* so it can't be Collections.emptySet() or some such thing
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Set<Include> theIncludes,
|
public Set<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Collection<Include> theIncludes,
|
||||||
boolean theReverseMode, DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest, Integer theMaxCount) {
|
boolean theReverseMode, DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest, Integer theMaxCount) {
|
||||||
if (theMatches.size() == 0) {
|
if (theMatches.size() == 0) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
|
@ -1132,6 +1132,8 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
List<String> paths;
|
List<String> paths;
|
||||||
|
|
||||||
|
// Start replace
|
||||||
RuntimeSearchParam param;
|
RuntimeSearchParam param;
|
||||||
String resType = nextInclude.getParamType();
|
String resType = nextInclude.getParamType();
|
||||||
if (isBlank(resType)) {
|
if (isBlank(resType)) {
|
||||||
|
@ -1154,7 +1156,8 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
paths = theReverseMode ? param.getPathsSplitForResourceType(resType) : param.getPathsSplit();
|
paths = param.getPathsSplitForResourceType(resType);
|
||||||
|
// end replace
|
||||||
|
|
||||||
String targetResourceType = defaultString(nextInclude.getParamTargetType(), null);
|
String targetResourceType = defaultString(nextInclude.getParamTargetType(), null);
|
||||||
for (String nextPath : paths) {
|
for (String nextPath : paths) {
|
||||||
|
@ -1224,10 +1227,10 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
q.setParameter("target_resource_types", param.getTargets());
|
q.setParameter("target_resource_types", param.getTargets());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Tuple> results = q.getResultList();
|
|
||||||
if (theMaxCount != null) {
|
if (theMaxCount != null) {
|
||||||
q.setMaxResults(theMaxCount);
|
q.setMaxResults(theMaxCount);
|
||||||
}
|
}
|
||||||
|
List<Tuple> results = q.getResultList();
|
||||||
for (Tuple result : results) {
|
for (Tuple result : results) {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
Long resourceId = NumberUtils.createLong(String.valueOf(result.get(RESOURCE_ID_ALIAS)));
|
Long resourceId = NumberUtils.createLong(String.valueOf(result.get(RESOURCE_ID_ALIAS)));
|
||||||
|
|
|
@ -90,15 +90,7 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
@Override
|
@Override
|
||||||
public Search save(Search theSearch) {
|
public Search save(Search theSearch) {
|
||||||
Search newSearch;
|
Search newSearch = mySearchDao.save(theSearch);
|
||||||
if (theSearch.getId() == null) {
|
|
||||||
newSearch = mySearchDao.save(theSearch);
|
|
||||||
for (SearchInclude next : theSearch.getIncludes()) {
|
|
||||||
mySearchIncludeDao.save(next);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newSearch = mySearchDao.save(theSearch);
|
|
||||||
}
|
|
||||||
return newSearch;
|
return newSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import ca.uhn.fhir.mdm.util.MdmResourceUtil;
|
||||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -23,10 +22,8 @@ import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
|
@ -239,6 +239,9 @@ public class SearchParameterMap implements Serializable {
|
||||||
b.append(Constants.PARAM_INCLUDE_QUALIFIER_RECURSE);
|
b.append(Constants.PARAM_INCLUDE_QUALIFIER_RECURSE);
|
||||||
}
|
}
|
||||||
b.append('=');
|
b.append('=');
|
||||||
|
if (Constants.INCLUDE_STAR.equals(nextInclude.getValue())) {
|
||||||
|
b.append(Constants.INCLUDE_STAR);
|
||||||
|
} else {
|
||||||
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamType()));
|
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamType()));
|
||||||
b.append(':');
|
b.append(':');
|
||||||
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamName()));
|
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamName()));
|
||||||
|
@ -248,6 +251,7 @@ public class SearchParameterMap implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addUrlParamSeparator(StringBuilder theB) {
|
private void addUrlParamSeparator(StringBuilder theB) {
|
||||||
if (theB.length() == 0) {
|
if (theB.length() == 0) {
|
||||||
|
@ -587,6 +591,13 @@ public class SearchParameterMap implements Serializable {
|
||||||
return myIncludes != null && !myIncludes.isEmpty();
|
return myIncludes != null && !myIncludes.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 6.2.0
|
||||||
|
*/
|
||||||
|
public boolean hasRevIncludes() {
|
||||||
|
return myRevIncludes != null && !myRevIncludes.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||||
|
|
|
@ -39,6 +39,27 @@ class SearchParameterMapTest {
|
||||||
assertEquals("?_lastUpdated=ge2021-05-31", map.toNormalizedQueryString(ourFhirContext));
|
assertEquals("?_lastUpdated=ge2021-05-31", map.toNormalizedQueryString(ourFhirContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toNormalizedQueryString_IncludeNormal() {
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.addInclude(new Include("Patient:name"));
|
||||||
|
assertEquals("?_include=Patient:name", map.toNormalizedQueryString(ourFhirContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toNormalizedQueryString_IncludeStar() {
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.addInclude(new Include("*"));
|
||||||
|
assertEquals("?_include=*", map.toNormalizedQueryString(ourFhirContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toNormalizedQueryString_IncludeTypedStar() {
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.addInclude(new Include("Patient:*"));
|
||||||
|
assertEquals("?_include=Patient:*", map.toNormalizedQueryString(ourFhirContext));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void toNormalizedQueryStringUpper() {
|
void toNormalizedQueryStringUpper() {
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
|
|
@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||||
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.jpa.search.PersistedJpaSearchFirstPageBundleProvider;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
||||||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||||
|
@ -20,6 +21,7 @@ import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
|
import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
|
||||||
import ca.uhn.fhir.util.BundleBuilder;
|
import ca.uhn.fhir.util.BundleBuilder;
|
||||||
|
@ -917,6 +919,7 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
||||||
|
|
||||||
myCaptureQueriesListener.clear();
|
myCaptureQueriesListener.clear();
|
||||||
IBundleProvider outcome = myPatientDao.search(map);
|
IBundleProvider outcome = myPatientDao.search(map);
|
||||||
|
assertEquals(SimpleBundleProvider.class, outcome.getClass());
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(outcome), containsInAnyOrder(
|
assertThat(toUnqualifiedVersionlessIdValues(outcome), containsInAnyOrder(
|
||||||
"Patient/P1", "CareTeam/CT1-0", "CareTeam/CT1-1", "CareTeam/CT1-2",
|
"Patient/P1", "CareTeam/CT1-0", "CareTeam/CT1-1", "CareTeam/CT1-2",
|
||||||
"Patient/P2", "CareTeam/CT2-0", "CareTeam/CT2-1", "CareTeam/CT2-2"
|
"Patient/P2", "CareTeam/CT2-0", "CareTeam/CT2-1", "CareTeam/CT2-2"
|
||||||
|
@ -929,6 +932,115 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
||||||
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMultipleIncludes_Async() {
|
||||||
|
// Setup
|
||||||
|
createPatient(withId("A"), withFamily("Hello"));
|
||||||
|
createEncounter(withId("E"), withIdentifier("http://foo", "bar"));
|
||||||
|
createObservation(withId("O"), withSubject("Patient/A"), withEncounter("Encounter/E"));
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Test
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.addInclude(Observation.INCLUDE_ENCOUNTER);
|
||||||
|
map.addInclude(Observation.INCLUDE_PATIENT);
|
||||||
|
map.addInclude(Observation.INCLUDE_SUBJECT);
|
||||||
|
IBundleProvider results = myObservationDao.search(map, mySrd);
|
||||||
|
assertEquals(PersistedJpaSearchFirstPageBundleProvider.class, results.getClass());
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(ids, containsInAnyOrder("Patient/A", "Encounter/E", "Observation/O"));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
|
assertEquals(7, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
assertEquals(3, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||||
|
assertEquals(1, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
|
runInTransaction(()->{
|
||||||
|
assertEquals(1, mySearchEntityDao.count());
|
||||||
|
assertEquals(3, mySearchIncludeEntityDao.count());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMultipleIncludesRecurse_Async() {
|
||||||
|
// Setup
|
||||||
|
createPatient(withId("A"), withFamily("Hello"));
|
||||||
|
createEncounter(withId("E"), withIdentifier("http://foo", "bar"));
|
||||||
|
createObservation(withId("O"), withSubject("Patient/A"), withEncounter("Encounter/E"));
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Test
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.addInclude(Observation.INCLUDE_ENCOUNTER.asRecursive());
|
||||||
|
map.addInclude(Observation.INCLUDE_PATIENT.asRecursive());
|
||||||
|
map.addInclude(Observation.INCLUDE_SUBJECT.asRecursive());
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map, mySrd));
|
||||||
|
assertThat(ids, containsInAnyOrder("Patient/A", "Encounter/E", "Observation/O"));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
|
assertEquals(10, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
assertEquals(3, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||||
|
assertEquals(1, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMultipleIncludes_Sync() {
|
||||||
|
// Setup
|
||||||
|
createPatient(withId("A"), withFamily("Hello"));
|
||||||
|
createEncounter(withId("E"), withIdentifier("http://foo", "bar"));
|
||||||
|
createObservation(withId("O"), withSubject("Patient/A"), withEncounter("Encounter/E"));
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Test
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.setLoadSynchronous(true);
|
||||||
|
map.addInclude(Observation.INCLUDE_ENCOUNTER);
|
||||||
|
map.addInclude(Observation.INCLUDE_PATIENT);
|
||||||
|
map.addInclude(Observation.INCLUDE_SUBJECT);
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map, mySrd));
|
||||||
|
assertThat(ids, containsInAnyOrder("Patient/A", "Encounter/E", "Observation/O"));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
|
assertEquals(5, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithMultipleIncludesRecurse_Sync() {
|
||||||
|
// Setup
|
||||||
|
createPatient(withId("A"), withFamily("Hello"));
|
||||||
|
createEncounter(withId("E"), withIdentifier("http://foo", "bar"));
|
||||||
|
createObservation(withId("O"), withSubject("Patient/A"), withEncounter("Encounter/E"));
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
// Test
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
map.setLoadSynchronous(true);
|
||||||
|
map.addInclude(Observation.INCLUDE_ENCOUNTER.asRecursive());
|
||||||
|
map.addInclude(Observation.INCLUDE_PATIENT.asRecursive());
|
||||||
|
map.addInclude(Observation.INCLUDE_SUBJECT.asRecursive());
|
||||||
|
ids = toUnqualifiedVersionlessIdValues(myObservationDao.search(map, mySrd));
|
||||||
|
assertThat(ids, containsInAnyOrder("Patient/A", "Encounter/E", "Observation/O"));
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
|
assertEquals(8, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithMultipleCreates() {
|
public void testTransactionWithMultipleCreates() {
|
||||||
myDaoConfig.setMassIngestionMode(true);
|
myDaoConfig.setMassIngestionMode(true);
|
||||||
|
|
|
@ -876,7 +876,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
List<IIdType> actual = toUnqualifiedVersionlessIds(resp);
|
List<IIdType> actual = toUnqualifiedVersionlessIds(resp);
|
||||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
assertThat(actual, containsInAnyOrder(orgId, medId, patId, moId, patId2));
|
assertThat(actual, containsInAnyOrder(orgId, medId, patId, moId, patId2));
|
||||||
assertEquals(7, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
assertEquals(6, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
|
||||||
// Specific patient ID with linked stuff
|
// Specific patient ID with linked stuff
|
||||||
request = mock(HttpServletRequest.class);
|
request = mock(HttpServletRequest.class);
|
||||||
|
|
|
@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
import ca.uhn.fhir.jpa.entity.SearchResult;
|
||||||
|
@ -30,8 +29,6 @@ public class SearchCoordinatorSvcImplTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchResultDao mySearchResultDao;
|
private ISearchResultDao mySearchResultDao;
|
||||||
@Autowired
|
|
||||||
private ISearchIncludeDao mySearchIncludeDao;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchCoordinatorSvc mySearchCoordinator;
|
private ISearchCoordinatorSvc mySearchCoordinator;
|
||||||
|
@ -52,7 +49,6 @@ public class SearchCoordinatorSvcImplTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
runInTransaction(()->{
|
runInTransaction(()->{
|
||||||
mySearchResultDao.deleteAll();
|
mySearchResultDao.deleteAll();
|
||||||
mySearchIncludeDao.deleteAll();
|
|
||||||
mySearchDao.deleteAll();
|
mySearchDao.deleteAll();
|
||||||
});
|
});
|
||||||
runInTransaction(()->{
|
runInTransaction(()->{
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ca.uhn.fhir.jpa.provider.r4;
|
package ca.uhn.fhir.jpa.provider.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.entity.SearchInclude;
|
|
||||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
import ca.uhn.fhir.jpa.entity.SearchResult;
|
||||||
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
|
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
@ -42,8 +40,6 @@ public class StaleSearchDeletingSvcR4Test extends BaseResourceProviderR4Test {
|
||||||
private ISearchDao mySearchEntityDao;
|
private ISearchDao mySearchEntityDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchResultDao mySearchResultDao;
|
private ISearchResultDao mySearchResultDao;
|
||||||
@Autowired
|
|
||||||
private ISearchIncludeDao mySearchIncludeDao;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@AfterEach()
|
@AfterEach()
|
||||||
|
@ -136,10 +132,6 @@ public class StaleSearchDeletingSvcR4Test extends BaseResourceProviderR4Test {
|
||||||
mySearchResultDao.save(sr);
|
mySearchResultDao.save(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SearchInclude si = new SearchInclude(search, "Patient:name", false, false);
|
|
||||||
mySearchIncludeDao.save(si);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// It should take two passes to delete the search fully
|
// It should take two passes to delete the search fully
|
||||||
|
|
|
@ -57,6 +57,7 @@ import ca.uhn.fhir.jpa.dao.data.IResourceReindexJobDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ITagDefinitionDao;
|
import ca.uhn.fhir.jpa.dao.data.ITagDefinitionDao;
|
||||||
|
@ -237,6 +238,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
|
||||||
protected ITermCodeSystemStorageSvc myTermCodeSystemStorageSvc;
|
protected ITermCodeSystemStorageSvc myTermCodeSystemStorageSvc;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ISearchDao mySearchEntityDao;
|
protected ISearchDao mySearchEntityDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ISearchIncludeDao mySearchIncludeEntityDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ISearchResultDao mySearchResultDao;
|
protected ISearchResultDao mySearchResultDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -74,18 +74,6 @@ public class BulkExportCreateReportStep implements IReductionStepWorker<BulkExpo
|
||||||
return RunOutcome.SUCCESS;
|
return RunOutcome.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getOriginatingRequestUrl(@Nonnull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails, BulkExportJobResults results) {
|
|
||||||
IJobInstance instance = theStepExecutionDetails.getInstance();
|
|
||||||
String url = "";
|
|
||||||
if (instance instanceof JobInstance) {
|
|
||||||
JobInstance jobInstance = (JobInstance) instance;
|
|
||||||
BulkExportJobParameters parameters = jobInstance.getParameters(BulkExportJobParameters.class);
|
|
||||||
String originalRequestUrl = parameters.getOriginalRequestUrl();
|
|
||||||
url = originalRequestUrl;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public ChunkOutcome consume(ChunkExecutionDetails<BulkExportJobParameters,
|
public ChunkOutcome consume(ChunkExecutionDetails<BulkExportJobParameters,
|
||||||
|
@ -101,4 +89,16 @@ public class BulkExportCreateReportStep implements IReductionStepWorker<BulkExpo
|
||||||
|
|
||||||
return ChunkOutcome.SUCCESS();
|
return ChunkOutcome.SUCCESS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getOriginatingRequestUrl(@Nonnull StepExecutionDetails<BulkExportJobParameters, BulkExportBinaryFileId> theStepExecutionDetails, BulkExportJobResults results) {
|
||||||
|
IJobInstance instance = theStepExecutionDetails.getInstance();
|
||||||
|
String url = "";
|
||||||
|
if (instance instanceof JobInstance) {
|
||||||
|
JobInstance jobInstance = (JobInstance) instance;
|
||||||
|
BulkExportJobParameters parameters = jobInstance.getParameters(BulkExportJobParameters.class);
|
||||||
|
String originalRequestUrl = parameters.getOriginalRequestUrl();
|
||||||
|
url = originalRequestUrl;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ import ca.uhn.fhir.batch2.importpull.models.Batch2BulkImportPullJobParameters;
|
||||||
import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc;
|
import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc;
|
||||||
import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobJson;
|
import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobJson;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class BulkImportParameterValidator implements IJobParametersValidator<Bat
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(@NotNull Batch2BulkImportPullJobParameters theParameters) {
|
public List<String> validate(@Nonnull Batch2BulkImportPullJobParameters theParameters) {
|
||||||
ourLog.info("BulkImportPull parameter validation begin");
|
ourLog.info("BulkImportPull parameter validation begin");
|
||||||
|
|
||||||
ArrayList<String> errors = new ArrayList<>();
|
ArrayList<String> errors = new ArrayList<>();
|
||||||
|
|
|
@ -30,9 +30,10 @@ import ca.uhn.fhir.batch2.importpull.models.Batch2BulkImportPullJobParameters;
|
||||||
import ca.uhn.fhir.batch2.importpull.models.BulkImportFilePartitionResult;
|
import ca.uhn.fhir.batch2.importpull.models.BulkImportFilePartitionResult;
|
||||||
import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc;
|
import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc;
|
||||||
import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobJson;
|
import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobJson;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
public class FetchPartitionedFilesStep implements IFirstJobStepWorker<Batch2BulkImportPullJobParameters, BulkImportFilePartitionResult> {
|
public class FetchPartitionedFilesStep implements IFirstJobStepWorker<Batch2BulkImportPullJobParameters, BulkImportFilePartitionResult> {
|
||||||
|
@ -44,11 +45,11 @@ public class FetchPartitionedFilesStep implements IFirstJobStepWorker<Batch2Bulk
|
||||||
myBulkDataImportSvc = theBulkDataImportSvc;
|
myBulkDataImportSvc = theBulkDataImportSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<Batch2BulkImportPullJobParameters, VoidModel> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<Batch2BulkImportPullJobParameters, VoidModel> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<BulkImportFilePartitionResult> theDataSink
|
@Nonnull IJobDataSink<BulkImportFilePartitionResult> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
String jobId = theStepExecutionDetails.getParameters().getJobId();
|
String jobId = theStepExecutionDetails.getParameters().getJobId();
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ import ca.uhn.fhir.jpa.bulk.imprt.model.BulkImportJobFileJson;
|
||||||
import ca.uhn.fhir.jpa.bulk.imprt.model.JobFileRowProcessingModeEnum;
|
import ca.uhn.fhir.jpa.bulk.imprt.model.JobFileRowProcessingModeEnum;
|
||||||
import ca.uhn.fhir.util.IoUtil;
|
import ca.uhn.fhir.util.IoUtil;
|
||||||
import com.google.common.io.LineReader;
|
import com.google.common.io.LineReader;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
@ -51,13 +51,13 @@ public class ReadInResourcesFromFileStep implements IJobStepWorker<Batch2BulkImp
|
||||||
myBulkDataImportSvc = theBulkDataImportSvc;
|
myBulkDataImportSvc = theBulkDataImportSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// because we are using an unstable google api
|
// because we are using an unstable Google api
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<Batch2BulkImportPullJobParameters, BulkImportFilePartitionResult> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<Batch2BulkImportPullJobParameters, BulkImportFilePartitionResult> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<BulkImportRecord> theDataSink
|
@Nonnull IJobDataSink<BulkImportRecord> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
String jobId = theStepExecutionDetails.getParameters().getJobId();
|
String jobId = theStepExecutionDetails.getParameters().getJobId();
|
||||||
int fileIndex = theStepExecutionDetails.getData().getFileIndex();
|
int fileIndex = theStepExecutionDetails.getData().getFileIndex();
|
||||||
|
|
|
@ -35,10 +35,11 @@ import ca.uhn.fhir.jpa.bulk.imprt.model.JobFileRowProcessingModeEnum;
|
||||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class WriteBundleForImportStep implements ILastJobStepWorker<Batch2BulkImportPullJobParameters, BulkImportRecord> {
|
public class WriteBundleForImportStep implements ILastJobStepWorker<Batch2BulkImportPullJobParameters, BulkImportRecord> {
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(WriteBundleForImportStep.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(WriteBundleForImportStep.class);
|
||||||
|
@ -53,11 +54,11 @@ public class WriteBundleForImportStep implements ILastJobStepWorker<Batch2BulkIm
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"SwitchStatementWithTooFewBranches", "rawtypes", "unchecked"})
|
@SuppressWarnings({"SwitchStatementWithTooFewBranches", "rawtypes", "unchecked"})
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<Batch2BulkImportPullJobParameters, BulkImportRecord> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<Batch2BulkImportPullJobParameters, BulkImportRecord> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<VoidModel> theDataSink
|
@Nonnull IJobDataSink<VoidModel> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
|
|
||||||
BulkImportRecord record = theStepExecutionDetails.getData();
|
BulkImportRecord record = theStepExecutionDetails.getData();
|
||||||
|
|
|
@ -28,7 +28,8 @@ import ca.uhn.fhir.batch2.api.StepExecutionDetails;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DeleteCodeSystemConceptsByVersionStep implements IJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, CodeSystemVersionPIDResult> {
|
public class DeleteCodeSystemConceptsByVersionStep implements IJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, CodeSystemVersionPIDResult> {
|
||||||
|
|
||||||
|
@ -38,11 +39,11 @@ public class DeleteCodeSystemConceptsByVersionStep implements IJobStepWorker<Ter
|
||||||
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
@Nonnull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
CodeSystemVersionPIDResult versionPidResult = theStepExecutionDetails.getData();
|
CodeSystemVersionPIDResult versionPidResult = theStepExecutionDetails.getData();
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ import ca.uhn.fhir.batch2.model.ChunkOutcome;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DeleteCodeSystemStep implements IReductionStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, VoidModel> {
|
public class DeleteCodeSystemStep implements IReductionStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, VoidModel> {
|
||||||
|
|
||||||
|
@ -41,11 +42,11 @@ public class DeleteCodeSystemStep implements IReductionStepWorker<TermCodeSystem
|
||||||
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<VoidModel> theDataSink
|
@Nonnull IJobDataSink<VoidModel> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
// final step
|
// final step
|
||||||
long codeId = theStepExecutionDetails.getParameters().getTermPid();
|
long codeId = theStepExecutionDetails.getParameters().getTermPid();
|
||||||
|
@ -56,7 +57,7 @@ public class DeleteCodeSystemStep implements IReductionStepWorker<TermCodeSystem
|
||||||
return RunOutcome.SUCCESS;
|
return RunOutcome.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public ChunkOutcome consume(ChunkExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theChunkDetails) {
|
public ChunkOutcome consume(ChunkExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theChunkDetails) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -28,7 +28,8 @@ import ca.uhn.fhir.batch2.api.StepExecutionDetails;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DeleteCodeSystemVersionStep implements IJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, CodeSystemVersionPIDResult> {
|
public class DeleteCodeSystemVersionStep implements IJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult, CodeSystemVersionPIDResult> {
|
||||||
|
|
||||||
|
@ -38,11 +39,11 @@ public class DeleteCodeSystemVersionStep implements IJobStepWorker<TermCodeSyste
|
||||||
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
@Nonnull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
CodeSystemVersionPIDResult versionPidResult = theStepExecutionDetails.getData();
|
CodeSystemVersionPIDResult versionPidResult = theStepExecutionDetails.getData();
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ import ca.uhn.fhir.batch2.api.VoidModel;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class ReadTermConceptVersionsStep implements IFirstJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> {
|
public class ReadTermConceptVersionsStep implements IFirstJobStepWorker<TermCodeSystemDeleteJobParameters, CodeSystemVersionPIDResult> {
|
||||||
|
@ -41,11 +41,11 @@ public class ReadTermConceptVersionsStep implements IFirstJobStepWorker<TermCode
|
||||||
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myITermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteJobParameters, VoidModel> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteJobParameters, VoidModel> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
@Nonnull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
TermCodeSystemDeleteJobParameters parameters = theStepExecutionDetails.getParameters();
|
TermCodeSystemDeleteJobParameters parameters = theStepExecutionDetails.getParameters();
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ package ca.uhn.fhir.batch2.jobs.termcodesystem.codesystemdelete;
|
||||||
|
|
||||||
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public class TermCodeSystemDeleteJobParametersValidator implements IJobParameter
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(@NotNull TermCodeSystemDeleteJobParameters theParameters) {
|
public List<String> validate(@Nonnull TermCodeSystemDeleteJobParameters theParameters) {
|
||||||
List<String> errors = new ArrayList<>();
|
List<String> errors = new ArrayList<>();
|
||||||
if (theParameters.getTermPid() <= 0) {
|
if (theParameters.getTermPid() <= 0) {
|
||||||
errors.add("Invalid Term Code System PID " + theParameters.getTermPid());
|
errors.add("Invalid Term Code System PID " + theParameters.getTermPid());
|
||||||
|
|
|
@ -29,7 +29,8 @@ import ca.uhn.fhir.batch2.api.VoidModel;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DeleteCodeSystemVersionFinalStep implements ILastJobStepWorker<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> {
|
public class DeleteCodeSystemVersionFinalStep implements ILastJobStepWorker<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> {
|
||||||
|
|
||||||
|
@ -39,11 +40,11 @@ public class DeleteCodeSystemVersionFinalStep implements ILastJobStepWorker<Term
|
||||||
myTermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myTermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<VoidModel> theDataSink
|
@Nonnull IJobDataSink<VoidModel> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
long versionPid = theStepExecutionDetails.getParameters().getCodeSystemVersionPid();
|
long versionPid = theStepExecutionDetails.getParameters().getCodeSystemVersionPid();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,8 @@ import ca.uhn.fhir.batch2.api.VoidModel;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemDeleteJobSvc;
|
||||||
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
import ca.uhn.fhir.jpa.term.models.CodeSystemVersionPIDResult;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DeleteCodeSystemVersionFirstStep implements IFirstJobStepWorker<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> {
|
public class DeleteCodeSystemVersionFirstStep implements IFirstJobStepWorker<TermCodeSystemDeleteVersionJobParameters, CodeSystemVersionPIDResult> {
|
||||||
|
|
||||||
|
@ -39,11 +40,11 @@ public class DeleteCodeSystemVersionFirstStep implements IFirstJobStepWorker<Ter
|
||||||
myTermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
myTermCodeSystemSvc = theCodeSystemDeleteJobSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public RunOutcome run(
|
public RunOutcome run(
|
||||||
@NotNull StepExecutionDetails<TermCodeSystemDeleteVersionJobParameters, VoidModel> theStepExecutionDetails,
|
@Nonnull StepExecutionDetails<TermCodeSystemDeleteVersionJobParameters, VoidModel> theStepExecutionDetails,
|
||||||
@NotNull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
@Nonnull IJobDataSink<CodeSystemVersionPIDResult> theDataSink
|
||||||
) throws JobExecutionFailedException {
|
) throws JobExecutionFailedException {
|
||||||
long versionId = theStepExecutionDetails.getParameters().getCodeSystemVersionPid();
|
long versionId = theStepExecutionDetails.getParameters().getCodeSystemVersionPid();
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ package ca.uhn.fhir.batch2.jobs.termcodesystem.codesystemversiondelete;
|
||||||
|
|
||||||
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
|
||||||
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
import ca.uhn.fhir.jpa.term.models.TermCodeSystemDeleteVersionJobParameters;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public class DeleteCodeSystemVersionParameterValidator implements IJobParameters
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public List<String> validate(@NotNull TermCodeSystemDeleteVersionJobParameters theParameters) {
|
public List<String> validate(@Nonnull TermCodeSystemDeleteVersionJobParameters theParameters) {
|
||||||
ArrayList<String> errors = new ArrayList<>();
|
ArrayList<String> errors = new ArrayList<>();
|
||||||
long versionPID = theParameters.getCodeSystemVersionPid();
|
long versionPID = theParameters.getCodeSystemVersionPid();
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public interface ISearchBuilder {
|
||||||
|
|
||||||
void loadResourcesByPid(Collection<ResourcePersistentId> thePids, Collection<ResourcePersistentId> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails);
|
void loadResourcesByPid(Collection<ResourcePersistentId> thePids, Collection<ResourcePersistentId> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails);
|
||||||
|
|
||||||
Set<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Set<Include> theRevIncludes, boolean theReverseMode,
|
Set<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Collection<Include> theRevIncludes, boolean theReverseMode,
|
||||||
DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest, Integer theMaxCount);
|
DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest, Integer theMaxCount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,13 +15,13 @@ import org.hl7.fhir.r4.model.Enumerations;
|
||||||
import org.hl7.fhir.r4.model.Extension;
|
import org.hl7.fhir.r4.model.Extension;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.r4.model.SearchParameter;
|
import org.hl7.fhir.r4.model.SearchParameter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -37,27 +37,21 @@ import static org.mockito.Mockito.when;
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
public class SearchParameterValidatingInterceptorTest {
|
public class SearchParameterValidatingInterceptorTest {
|
||||||
|
|
||||||
static final FhirContext ourFhirContext = FhirContext.forR4();
|
|
||||||
public static final String UPLIFT_URL = "https://some-url";
|
public static final String UPLIFT_URL = "https://some-url";
|
||||||
|
static final FhirContext ourFhirContext = FhirContext.forR4();
|
||||||
|
static String ID1 = "ID1";
|
||||||
|
static String ID2 = "ID2";
|
||||||
@Mock
|
@Mock
|
||||||
RequestDetails myRequestDetails;
|
RequestDetails myRequestDetails;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
IFhirResourceDao myIFhirResourceDao;
|
IFhirResourceDao myIFhirResourceDao;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
DaoRegistry myDaoRegistry;
|
DaoRegistry myDaoRegistry;
|
||||||
@Mock
|
@Mock
|
||||||
IIdHelperService myIdHelperService;
|
IIdHelperService myIdHelperService;
|
||||||
|
|
||||||
SearchParamValidatingInterceptor mySearchParamValidatingInterceptor;
|
SearchParamValidatingInterceptor mySearchParamValidatingInterceptor;
|
||||||
|
|
||||||
SearchParameter myExistingSearchParameter;
|
SearchParameter myExistingSearchParameter;
|
||||||
|
|
||||||
static String ID1 = "ID1";
|
|
||||||
static String ID2 = "ID2";
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeEach() {
|
public void beforeEach() {
|
||||||
|
|
||||||
|
@ -177,7 +171,7 @@ public class SearchParameterValidatingInterceptorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nonnull
|
||||||
private SearchParameter buildSearchParameterWithUpliftExtension(String theID) {
|
private SearchParameter buildSearchParameterWithUpliftExtension(String theID) {
|
||||||
SearchParameter newSearchParam = buildSearchParameterWithId(theID);
|
SearchParameter newSearchParam = buildSearchParameterWithId(theID);
|
||||||
|
|
||||||
|
@ -206,6 +200,7 @@ public class SearchParameterValidatingInterceptorTest {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
when(myIFhirResourceDao.searchForIds(any(), any())).thenReturn(resourcePersistentIds);
|
when(myIFhirResourceDao.searchForIds(any(), any())).thenReturn(resourcePersistentIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPersistedSearchParameters(List<SearchParameter> theSearchParams) {
|
private void setPersistedSearchParameters(List<SearchParameter> theSearchParams) {
|
||||||
when(myIFhirResourceDao.search(any(), any())).thenReturn(new SimpleBundleProvider(theSearchParams));
|
when(myIFhirResourceDao.search(any(), any())).thenReturn(new SimpleBundleProvider(theSearchParams));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,12 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.ICompositeType;
|
import org.hl7.fhir.instance.model.api.ICompositeType;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.InstantType;
|
import org.hl7.fhir.r4.model.InstantType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -179,6 +181,10 @@ public interface ITestDataBuilder {
|
||||||
return t -> t.getMeta().setLastUpdated(new InstantType(theIsoDate).getValue());
|
return t -> t.getMeta().setLastUpdated(new InstantType(theIsoDate).getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default IIdType createEncounter(Consumer<IBaseResource>... theModifiers) {
|
||||||
|
return createResource("Encounter", theModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
default IIdType createObservation(Consumer<IBaseResource>... theModifiers) {
|
default IIdType createObservation(Consumer<IBaseResource>... theModifiers) {
|
||||||
return createResource("Observation", theModifiers);
|
return createResource("Observation", theModifiers);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +196,6 @@ public interface ITestDataBuilder {
|
||||||
default IBaseResource buildPatient(Consumer<IBaseResource>... theModifiers) {
|
default IBaseResource buildPatient(Consumer<IBaseResource>... theModifiers) {
|
||||||
return buildResource("Patient", theModifiers);
|
return buildResource("Patient", theModifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
default IIdType createPatient(Consumer<IBaseResource>... theModifiers) {
|
default IIdType createPatient(Consumer<IBaseResource>... theModifiers) {
|
||||||
return createResource("Patient", theModifiers);
|
return createResource("Patient", theModifiers);
|
||||||
}
|
}
|
||||||
|
@ -223,13 +228,26 @@ public interface ITestDataBuilder {
|
||||||
|
|
||||||
|
|
||||||
default Consumer<IBaseResource> withSubject(@Nullable IIdType theSubject) {
|
default Consumer<IBaseResource> withSubject(@Nullable IIdType theSubject) {
|
||||||
|
return withReference("subject", theSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
default Consumer<IBaseResource> withSubject(@Nullable String theSubject) {
|
||||||
|
return withSubject(new IdType(theSubject));
|
||||||
|
}
|
||||||
|
|
||||||
|
default Consumer<IBaseResource> withEncounter(@Nullable String theEncounter) {
|
||||||
|
return withReference("encounter", new IdType(theEncounter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private Consumer<IBaseResource> withReference(String theReferenceName, @Nullable IIdType theReferenceValue) {
|
||||||
return t -> {
|
return t -> {
|
||||||
if (theSubject != null) {
|
if (theReferenceValue != null && theReferenceValue.getValue() != null) {
|
||||||
IBaseReference reference = (IBaseReference) getFhirContext().getElementDefinition("Reference").newInstance();
|
IBaseReference reference = (IBaseReference) getFhirContext().getElementDefinition("Reference").newInstance();
|
||||||
reference.setReference(theSubject.getValue());
|
reference.setReference(theReferenceValue.getValue());
|
||||||
|
|
||||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
||||||
resourceDef.getChildByName("subject").getMutator().addValue(t, reference);
|
resourceDef.getChildByName(theReferenceName).getMutator().addValue(t, reference);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -301,27 +319,11 @@ public interface ITestDataBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
default Consumer<IBaseResource> withObservationHasMember(@Nullable IIdType theHasMember) {
|
default Consumer<IBaseResource> withObservationHasMember(@Nullable IIdType theHasMember) {
|
||||||
return t -> {
|
return withReference("hasMember", theHasMember);
|
||||||
if (theHasMember != null) {
|
|
||||||
IBaseReference reference = (IBaseReference) getFhirContext().getElementDefinition("Reference").newInstance();
|
|
||||||
reference.setReference(theHasMember.getValue());
|
|
||||||
|
|
||||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
|
||||||
resourceDef.getChildByName("hasMember").getMutator().addValue(t, reference);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default Consumer<IBaseResource> withOrganization(@Nullable IIdType theHasMember) {
|
default Consumer<IBaseResource> withOrganization(@Nullable IIdType theHasMember) {
|
||||||
return t -> {
|
return withReference("managingOrganization", theHasMember);
|
||||||
if (theHasMember != null) {
|
|
||||||
IBaseReference reference = (IBaseReference) getFhirContext().getElementDefinition("Reference").newInstance();
|
|
||||||
reference.setReference(theHasMember.getValue());
|
|
||||||
|
|
||||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(t.getClass());
|
|
||||||
resourceDef.getChildByName("managingOrganization").getMutator().addValue(t, reference);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo mb extract these to something like TestDataBuilderBacking. Maybe split out create* into child interface since people skip it.
|
// todo mb extract these to something like TestDataBuilderBacking. Maybe split out create* into child interface since people skip it.
|
||||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.test.utilities;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||||
|
@ -30,7 +29,6 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
|
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
|
||||||
import ca.uhn.fhir.rest.server.IncomingRequestAddressStrategy;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
||||||
|
@ -186,6 +184,10 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
return myRestServer.getObservationResourceProvider();
|
return myRestServer.getObservationResourceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
||||||
|
myRestServer.setObservationResourceProvider(theResourceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
return myRestServer.getPatientResourceProvider();
|
return myRestServer.getPatientResourceProvider();
|
||||||
|
@ -234,10 +236,6 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
return myRestServer.myRequestVerbs;
|
return myRestServer.myRequestVerbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
|
||||||
myRestServer.setObservationResourceProvider(theResourceProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Map<String, String>> getRequestHeaders() {
|
public List<Map<String, String>> getRequestHeaders() {
|
||||||
return myRestServer.myRequestHeaders;
|
return myRestServer.myRequestHeaders;
|
||||||
}
|
}
|
||||||
|
@ -252,15 +250,15 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MyRestfulServer extends RestfulServer {
|
private static class MyRestfulServer extends RestfulServer {
|
||||||
|
private final List<String> myRequestUrls = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private final List<String> myRequestVerbs = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private final List<Map<String, String>> myRequestHeaders = Collections.synchronizedList(new ArrayList<>());
|
||||||
private boolean myFailNextPut;
|
private boolean myFailNextPut;
|
||||||
private HashMapResourceProvider<Patient> myPatientResourceProvider;
|
private HashMapResourceProvider<Patient> myPatientResourceProvider;
|
||||||
private HashMapResourceProvider<Observation> myObservationResourceProvider;
|
private HashMapResourceProvider<Observation> myObservationResourceProvider;
|
||||||
private HashMapResourceProvider<Organization> myOrganizationResourceProvider;
|
private HashMapResourceProvider<Organization> myOrganizationResourceProvider;
|
||||||
private HashMapResourceProvider<ConceptMap> myConceptMapResourceProvider;
|
private HashMapResourceProvider<ConceptMap> myConceptMapResourceProvider;
|
||||||
private RestServerDstu3Helper.MyPlainProvider myPlainProvider;
|
private RestServerDstu3Helper.MyPlainProvider myPlainProvider;
|
||||||
private final List<String> myRequestUrls = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
private final List<String> myRequestVerbs = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
private final List<Map<String, String>> myRequestHeaders= Collections.synchronizedList(new ArrayList<>());
|
|
||||||
|
|
||||||
public MyRestfulServer(FhirContext theFhirContext) {
|
public MyRestfulServer(FhirContext theFhirContext) {
|
||||||
super(theFhirContext);
|
super(theFhirContext);
|
||||||
|
@ -321,6 +319,14 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
return myObservationResourceProvider;
|
return myObservationResourceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
||||||
|
myObservationResourceProvider.getStoredResources().forEach(o -> theResourceProvider.store(o));
|
||||||
|
|
||||||
|
unregisterProvider(myObservationResourceProvider);
|
||||||
|
registerProvider(theResourceProvider);
|
||||||
|
myObservationResourceProvider = theResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
public HashMapResourceProvider<Organization> getOrganizationResourceProvider() {
|
public HashMapResourceProvider<Organization> getOrganizationResourceProvider() {
|
||||||
return myOrganizationResourceProvider;
|
return myOrganizationResourceProvider;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +335,14 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
return myConceptMapResourceProvider;
|
return myConceptMapResourceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
||||||
|
myConceptMapResourceProvider.getStoredResources().forEach(c -> theResourceProvider.store(c));
|
||||||
|
|
||||||
|
unregisterProvider(myConceptMapResourceProvider);
|
||||||
|
registerProvider(theResourceProvider);
|
||||||
|
myConceptMapResourceProvider = theResourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
public HashMapResourceProvider<Patient> getPatientResourceProvider() {
|
||||||
return myPatientResourceProvider;
|
return myPatientResourceProvider;
|
||||||
}
|
}
|
||||||
|
@ -353,23 +367,6 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
||||||
setPagingProvider(new FifoMemoryPagingProvider(20));
|
setPagingProvider(new FifoMemoryPagingProvider(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
|
||||||
myObservationResourceProvider.getStoredResources().forEach(o -> theResourceProvider.store(o));
|
|
||||||
|
|
||||||
unregisterProvider(myObservationResourceProvider);
|
|
||||||
registerProvider(theResourceProvider);
|
|
||||||
myObservationResourceProvider = theResourceProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConceptMapResourceProvider(HashMapResourceProvider<ConceptMap> theResourceProvider) {
|
|
||||||
myConceptMapResourceProvider.getStoredResources().forEach(c -> theResourceProvider.store(c));
|
|
||||||
|
|
||||||
unregisterProvider(myConceptMapResourceProvider);
|
|
||||||
registerProvider(theResourceProvider);
|
|
||||||
myConceptMapResourceProvider = theResourceProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class MyHashMapResourceProvider<T extends IBaseResource> extends HashMapResourceProvider<T> {
|
public class MyHashMapResourceProvider<T extends IBaseResource> extends HashMapResourceProvider<T> {
|
||||||
public MyHashMapResourceProvider(FhirContext theContext, Class theType) {
|
public MyHashMapResourceProvider(FhirContext theContext, Class theType) {
|
||||||
super(theContext, theType);
|
super(theContext, theType);
|
||||||
|
|
|
@ -6,7 +6,6 @@ import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Map;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
public class NpmPackageValidationSupportTest {
|
public class NpmPackageValidationSupportTest {
|
||||||
|
|
||||||
|
@ -34,6 +33,7 @@ public class NpmPackageValidationSupportTest {
|
||||||
"dummyBinary1.txt", "myDummyContent1".getBytes(),
|
"dummyBinary1.txt", "myDummyContent1".getBytes(),
|
||||||
"dummyBinary2.txt", "myDummyContent2".getBytes()
|
"dummyBinary2.txt", "myDummyContent2".getBytes()
|
||||||
);
|
);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateWithPackage() throws IOException {
|
public void testValidateWithPackage() throws IOException {
|
||||||
|
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -2013,7 +2013,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
<version>3.1.2</version>
|
<version>3.2.0</version>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.puppycrawl.tools</groupId>
|
<groupId>com.puppycrawl.tools</groupId>
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
<property name="format" value="System\.out\.println"/>
|
<property name="format" value="System\.out\.println"/>
|
||||||
<property name="ignoreComments" value="true"/>
|
<property name="ignoreComments" value="true"/>
|
||||||
</module>
|
</module>
|
||||||
|
<module name="RegexpSinglelineJava">
|
||||||
|
<property name="format" value="org\.jetbrains\.annotations\.NotNull"/>
|
||||||
|
</module>
|
||||||
|
<module name="RegexpSinglelineJava">
|
||||||
|
<property name="format" value="org\.jetbrains\.annotations\.Nullable"/>
|
||||||
|
</module>
|
||||||
<module name="AbstractClassName">
|
<module name="AbstractClassName">
|
||||||
<property name="format" value="^(Base|Abstract).+$"/>
|
<property name="format" value="^(Base|Abstract).+$"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -156,6 +156,6 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!--<kotlin.compiler.incremental>true</kotlin.compiler.incremental>-->
|
<!--<kotlin.compiler.incremental>true</kotlin.compiler.incremental>-->
|
||||||
<kotlin.version>1.5.31</kotlin.version>
|
<kotlin.version>1.6.21</kotlin.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
|
Loading…
Reference in New Issue