Work on muiltitenancy
This commit is contained in:
parent
9df4c58122
commit
691f2c4e9a
|
@ -67,6 +67,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-structures-r5</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 1783
|
||||||
|
title: "In the JPA sevrer, if overriding built-in search parameters is not enabled, the server
|
||||||
|
will now return an error if a client tries to create a SearchParameter that is
|
||||||
|
trying to override one. Previously, the SearchParameter would be stored but silently ignored,
|
||||||
|
which was confusing."
|
|
@ -219,6 +219,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
retVal.setResourceType(theEntity.getResourceType());
|
retVal.setResourceType(theEntity.getResourceType());
|
||||||
retVal.setForcedId(theId.getIdPart());
|
retVal.setForcedId(theId.getIdPart());
|
||||||
retVal.setResource(theEntity);
|
retVal.setResource(theEntity);
|
||||||
|
retVal.setTenantId(theEntity.getTenantId());
|
||||||
theEntity.setForcedId(retVal);
|
theEntity.setForcedId(retVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1094,6 +1095,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
ResourceHistoryProvenanceEntity provenance = new ResourceHistoryProvenanceEntity();
|
ResourceHistoryProvenanceEntity provenance = new ResourceHistoryProvenanceEntity();
|
||||||
provenance.setResourceHistoryTable(historyEntry);
|
provenance.setResourceHistoryTable(historyEntry);
|
||||||
provenance.setResourceTable(entity);
|
provenance.setResourceTable(entity);
|
||||||
|
provenance.setTenantId(entity.getTenantId());
|
||||||
if (haveRequestId) {
|
if (haveRequestId) {
|
||||||
provenance.setRequestId(left(requestId, Constants.REQUEST_ID_LENGTH));
|
provenance.setRequestId(left(requestId, Constants.REQUEST_ID_LENGTH));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
|
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
|
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.SearchParamTypeEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.SearchParamTypeEnum;
|
||||||
|
@ -38,8 +36,6 @@ import java.util.List;
|
||||||
|
|
||||||
public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
|
public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchParamExtractor mySearchParamExtractor;
|
private ISearchParamExtractor mySearchParamExtractor;
|
||||||
|
|
||||||
|
@ -79,8 +75,9 @@ public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao
|
||||||
String expression = theResource.getXpath();
|
String expression = theResource.getXpath();
|
||||||
FhirContext context = getContext();
|
FhirContext context = getContext();
|
||||||
SearchParamTypeEnum type = theResource.getTypeElement().getValueAsEnum();
|
SearchParamTypeEnum type = theResource.getTypeElement().getValueAsEnum();
|
||||||
|
String code = theResource.getCode();
|
||||||
|
|
||||||
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
|
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,19 @@ package ca.uhn.fhir.jpa.dao.data;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Modifying;
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface IResourceIndexedSearchParamDateDao extends JpaRepository<ResourceIndexedSearchParamDate, Long> {
|
public interface IResourceIndexedSearchParamDateDao extends JpaRepository<ResourceIndexedSearchParamDate, Long> {
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("delete from ResourceIndexedSearchParamDate t WHERE t.myResourcePid = :resid")
|
@Query("delete from ResourceIndexedSearchParamDate t WHERE t.myResourcePid = :resid")
|
||||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||||
|
|
||||||
|
@Query("SELECT t FROM ResourceIndexedSearchParamDate t WHERE t.myResourcePid = :resId")
|
||||||
|
List<ResourceIndexedSearchParamDate> findAllForResourceId(@Param("resId") Long thePatientId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,9 @@ public class FhirResourceDaoSearchParameterDstu3 extends BaseHapiFhirResourceDao
|
||||||
String expression = theResource.getExpression();
|
String expression = theResource.getExpression();
|
||||||
FhirContext context = getContext();
|
FhirContext context = getContext();
|
||||||
Enumerations.SearchParamType type = theResource.getType();
|
Enumerations.SearchParamType type = theResource.getType();
|
||||||
|
String code = theResource.getCode();
|
||||||
|
|
||||||
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
|
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,14 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
@ -78,14 +81,15 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<Se
|
||||||
|
|
||||||
Enum<?> status = theResource.getStatus();
|
Enum<?> status = theResource.getStatus();
|
||||||
List<CodeType> base = theResource.getBase();
|
List<CodeType> base = theResource.getBase();
|
||||||
|
String code = theResource.getCode();
|
||||||
String expression = theResource.getExpression();
|
String expression = theResource.getExpression();
|
||||||
FhirContext context = getContext();
|
FhirContext context = getContext();
|
||||||
Enum<?> type = theResource.getType();
|
Enum<?> type = theResource.getType();
|
||||||
|
|
||||||
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
|
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void validateSearchParam(ISearchParamExtractor theSearchParamExtractor, Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
|
public static void validateSearchParam(ISearchParamRegistry theSearchParamRegistry, ISearchParamExtractor theSearchParamExtractor, String theCode, Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
|
||||||
if (theStatus == null) {
|
if (theStatus == null) {
|
||||||
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
|
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
|
||||||
}
|
}
|
||||||
|
@ -146,6 +150,19 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<Se
|
||||||
|
|
||||||
}
|
}
|
||||||
} // if have expression
|
} // if have expression
|
||||||
|
|
||||||
|
// If overriding built-in SPs is disabled on this server, make sure we aren't
|
||||||
|
// doing that
|
||||||
|
if (theDaoConfig.getModelConfig().isDefaultSearchParamsCanBeOverridden() == false) {
|
||||||
|
for (IPrimitiveType<?> nextBaseType : theBase) {
|
||||||
|
String nextBase = nextBaseType.getValueAsString();
|
||||||
|
RuntimeSearchParam existingSearchParam = theSearchParamRegistry.getActiveSearchParam(nextBase, theCode);
|
||||||
|
if (existingSearchParam.getId() == null) {
|
||||||
|
throw new UnprocessableEntityException("Can not override built-in search parameter " + nextBase + ":" + theCode + " because overriding is disabled on this server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,11 +68,12 @@ public class FhirResourceDaoSearchParameterR5 extends BaseHapiFhirResourceDao<Se
|
||||||
|
|
||||||
Enum<?> status = theResource.getStatus();
|
Enum<?> status = theResource.getStatus();
|
||||||
List<CodeType> base = theResource.getBase();
|
List<CodeType> base = theResource.getBase();
|
||||||
|
String code = theResource.getCode();
|
||||||
String expression = theResource.getExpression();
|
String expression = theResource.getExpression();
|
||||||
FhirContext context = getContext();
|
FhirContext context = getContext();
|
||||||
Enum<?> type = theResource.getType();
|
Enum<?> type = theResource.getType();
|
||||||
|
|
||||||
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamExtractor, type, status, base, expression, context, getConfig());
|
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,27 +2,39 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.DateType;
|
||||||
|
import org.hl7.fhir.r4.model.Enumerations;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.SampledData;
|
||||||
|
import org.hl7.fhir.r4.model.SearchParameter;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.matchesPattern;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4CreateTest.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4CreateTest.class);
|
||||||
|
@ -31,6 +43,7 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
public void afterResetDao() {
|
public void afterResetDao() {
|
||||||
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
||||||
myDaoConfig.setResourceClientIdStrategy(new DaoConfig().getResourceClientIdStrategy());
|
myDaoConfig.setResourceClientIdStrategy(new DaoConfig().getResourceClientIdStrategy());
|
||||||
|
myDaoConfig.setDefaultSearchParamsCanBeOverridden(new DaoConfig().isDefaultSearchParamsCanBeOverridden());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -149,7 +162,7 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
p = new Patient();
|
p = new Patient();
|
||||||
p.setActive(false);
|
p.setActive(false);
|
||||||
try {
|
try {
|
||||||
myPatientDao.create(p).getId();
|
myPatientDao.create(p);
|
||||||
fail();
|
fail();
|
||||||
} catch (ResourceVersionConflictException e) {
|
} catch (ResourceVersionConflictException e) {
|
||||||
// good
|
// good
|
||||||
|
@ -280,6 +293,26 @@ public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideBuiltInSearchParamFailsIfDisabled() {
|
||||||
|
myModelConfig.setDefaultSearchParamsCanBeOverridden(false);
|
||||||
|
|
||||||
|
SearchParameter sp = new SearchParameter();
|
||||||
|
sp.setId("SearchParameter/patient-birthdate");
|
||||||
|
sp.setType(Enumerations.SearchParamType.DATE);
|
||||||
|
sp.setCode("birthdate");
|
||||||
|
sp.setExpression("Patient.birthDate");
|
||||||
|
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||||
|
sp.addBase("Patient");
|
||||||
|
try {
|
||||||
|
mySearchParameterDao.update(sp);
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("Can not override built-in search parameter Patient:birthdate because overriding is disabled on this server", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.*;
|
||||||
|
@ -32,10 +31,7 @@ import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.springframework.aop.framework.AopProxyUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.util.ProxyUtils;
|
|
||||||
import org.springframework.test.context.TestPropertySource;
|
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
@ -48,8 +44,17 @@ import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.INDEX_STATUS_INDEXED;
|
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.INDEX_STATUS_INDEXED;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.either;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -695,7 +700,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
assertEquals(1, myResourceReindexingSvc.forceReindexingPass());
|
assertEquals(1, myResourceReindexingSvc.forceReindexingPass());
|
||||||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||||
|
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||||
assertEquals(uniques.toString(), 1, uniques.size());
|
assertEquals(uniques.toString(), 1, uniques.size());
|
||||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||||
|
@ -712,7 +717,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||||
myResourceReindexingSvc.forceReindexingPass();
|
myResourceReindexingSvc.forceReindexingPass();
|
||||||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||||
|
|
||||||
runInTransaction(()->{
|
runInTransaction(() -> {
|
||||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||||
assertEquals(uniques.toString(), 1, uniques.size());
|
assertEquals(uniques.toString(), 1, uniques.size());
|
||||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||||
|
|
|
@ -4,8 +4,10 @@ import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
@ -17,6 +19,7 @@ import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.BooleanType;
|
import org.hl7.fhir.r4.model.BooleanType;
|
||||||
import org.hl7.fhir.r4.model.Enumerations;
|
import org.hl7.fhir.r4.model.Enumerations;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.Organization;
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
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;
|
||||||
|
@ -29,13 +32,13 @@ import javax.servlet.ServletException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ -43,6 +46,8 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MultitenantR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MultitenantR4Test.class);
|
||||||
private MyInterceptor myTenantInterceptor;
|
private MyInterceptor myTenantInterceptor;
|
||||||
|
private LocalDate myTenantDate;
|
||||||
|
private int myTenantId;
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
|
@ -58,6 +63,11 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
super.before();
|
super.before();
|
||||||
|
|
||||||
myDaoConfig.setMultiTenancyEnabled(true);
|
myDaoConfig.setMultiTenancyEnabled(true);
|
||||||
|
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||||
|
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||||
|
|
||||||
|
myTenantDate = LocalDate.of(2020, Month.JANUARY, 14);
|
||||||
|
myTenantId = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,12 +84,14 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResourceWithTenant() {
|
public void testCreateResourceWithTenant() {
|
||||||
createUniqueCompositeSp();
|
createUniqueCompositeSp();
|
||||||
|
createRequestId();
|
||||||
|
|
||||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
addCreateTenant(myTenantId, myTenantDate);
|
||||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
addCreateTenant(myTenantId, myTenantDate);
|
||||||
|
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.setName("org");
|
org.setName("org");
|
||||||
|
@ -91,75 +103,155 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
p.addIdentifier().setSystem("system").setValue("value");
|
p.addIdentifier().setSystem("system").setValue("value");
|
||||||
p.setBirthDate(new Date());
|
p.setBirthDate(new Date());
|
||||||
p.getManagingOrganization().setReferenceElement(orgId);
|
p.getManagingOrganization().setReferenceElement(orgId);
|
||||||
when(mySrd.getRequestId()).thenReturn("REQUEST_ID");
|
|
||||||
Long patientId = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
Long patientId = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||||
|
|
||||||
runInTransaction(() -> {
|
runInTransaction(() -> {
|
||||||
// HFJ_RESOURCE
|
// HFJ_RESOURCE
|
||||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||||
assertEquals(3, resourceTable.getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, resourceTable.getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), resourceTable.getTenantId().getTenantDate());
|
assertEquals(myTenantDate, resourceTable.getTenantId().getTenantDate());
|
||||||
|
|
||||||
resourceTable.getProfile()
|
|
||||||
|
|
||||||
// HFJ_RES_VER
|
// HFJ_RES_VER
|
||||||
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 1L);
|
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 1L);
|
||||||
assertEquals(3, version.getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, version.getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), version.getTenantId().getTenantDate());
|
assertEquals(myTenantDate, version.getTenantId().getTenantDate());
|
||||||
|
|
||||||
|
// HFJ_RES_VER_PROV
|
||||||
|
assertNotNull(version.getProvenance());
|
||||||
|
assertEquals(myTenantId, version.getProvenance().getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, version.getProvenance().getTenantId().getTenantDate());
|
||||||
|
|
||||||
// HFJ_SPIDX_STRING
|
// HFJ_SPIDX_STRING
|
||||||
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
|
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
|
||||||
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
|
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
|
||||||
assertEquals(10, strings.size());
|
assertEquals(10, strings.size());
|
||||||
assertEquals(3, strings.get(0).getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, strings.get(0).getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), strings.get(0).getTenantId().getTenantDate());
|
assertEquals(myTenantDate, strings.get(0).getTenantId().getTenantDate());
|
||||||
|
|
||||||
|
// HFJ_SPIDX_DATE
|
||||||
|
List<ResourceIndexedSearchParamDate> dates = myResourceIndexedSearchParamDateDao.findAllForResourceId(patientId);
|
||||||
|
ourLog.info("\n * {}", dates.stream().map(ResourceIndexedSearchParamDate::toString).collect(Collectors.joining("\n * ")));
|
||||||
|
assertEquals(2, dates.size());
|
||||||
|
assertEquals(myTenantId, dates.get(0).getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, dates.get(0).getTenantId().getTenantDate());
|
||||||
|
assertEquals(myTenantId, dates.get(1).getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, dates.get(1).getTenantId().getTenantDate());
|
||||||
|
|
||||||
// HFJ_RES_LINK
|
// HFJ_RES_LINK
|
||||||
List<ResourceLink> resourceLinks = myResourceLinkDao.findAllForResourceId(patientId);
|
List<ResourceLink> resourceLinks = myResourceLinkDao.findAllForResourceId(patientId);
|
||||||
assertEquals(1, resourceLinks.size());
|
assertEquals(1, resourceLinks.size());
|
||||||
assertEquals(3, resourceLinks.get(0).getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, resourceLinks.get(0).getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), resourceLinks.get(0).getTenantId().getTenantDate());
|
assertEquals(myTenantDate, resourceLinks.get(0).getTenantId().getTenantDate());
|
||||||
|
|
||||||
// HFJ_RES_PARAM_PRESENT
|
// HFJ_RES_PARAM_PRESENT
|
||||||
List<SearchParamPresent> presents = mySearchParamPresentDao.findAllForResource(resourceTable);
|
List<SearchParamPresent> presents = mySearchParamPresentDao.findAllForResource(resourceTable);
|
||||||
assertEquals(3, presents.size());
|
assertEquals(myTenantId, presents.size());
|
||||||
assertEquals(3, presents.get(0).getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, presents.get(0).getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), presents.get(0).getTenantId().getTenantDate());
|
assertEquals(myTenantDate, presents.get(0).getTenantId().getTenantDate());
|
||||||
|
|
||||||
// HFJ_IDX_CMP_STRING_UNIQ
|
// HFJ_IDX_CMP_STRING_UNIQ
|
||||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceId(patientId);
|
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceId(patientId);
|
||||||
assertEquals(3, uniques.size());
|
assertEquals(1, uniques.size());
|
||||||
assertEquals(3, uniques.get(0).getTenantId().getTenantId().intValue());
|
assertEquals(myTenantId, uniques.get(0).getTenantId().getTenantId().intValue());
|
||||||
assertEquals(LocalDate.of(2020, Month.JANUARY, 14), uniques.get(0).getTenantId().getTenantDate());
|
assertEquals(myTenantDate, uniques.get(0).getTenantId().getTenantDate());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateWithForcedId() {
|
||||||
|
addCreateTenant(myTenantId, myTenantDate);
|
||||||
|
addCreateTenant(myTenantId, myTenantDate);
|
||||||
|
|
||||||
|
Organization org = new Organization();
|
||||||
|
org.setId("org");
|
||||||
|
org.setName("org");
|
||||||
|
IIdType orgId = myOrganizationDao.update(org).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("pat");
|
||||||
|
p.getManagingOrganization().setReferenceElement(orgId);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
runInTransaction(() -> {
|
||||||
|
// HFJ_FORCED_ID
|
||||||
|
List<ForcedId> forcedIds = myForcedIdDao.findAll();
|
||||||
|
assertEquals(2, forcedIds.size());
|
||||||
|
assertEquals(myTenantId, forcedIds.get(0).getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, forcedIds.get(0).getTenantId().getTenantDate());
|
||||||
|
assertEquals(myTenantId, forcedIds.get(1).getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, forcedIds.get(1).getTenantId().getTenantDate());
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateResourceWithTenant() {
|
public void testUpdateResourceWithTenant() {
|
||||||
createUniqueCompositeSp();
|
createRequestId();
|
||||||
|
addCreateTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
||||||
addTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
|
|
||||||
|
|
||||||
|
// Create a resource
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setActive(true);
|
p.setActive(true);
|
||||||
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||||
|
runInTransaction(() -> {
|
||||||
|
// HFJ_RESOURCE
|
||||||
|
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||||
|
assertEquals(myTenantId, resourceTable.getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, resourceTable.getTenantId().getTenantDate());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update that resource
|
||||||
p = new Patient();
|
p = new Patient();
|
||||||
p.setId("Patient/" + patientId);
|
p.setId("Patient/" + patientId);
|
||||||
p.setActive(false);
|
p.setActive(false);
|
||||||
myPatientDao.update(p);
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
runInTransaction(() -> {
|
runInTransaction(() -> {
|
||||||
|
// HFJ_RESOURCE
|
||||||
|
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||||
|
assertEquals(myTenantId, resourceTable.getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, resourceTable.getTenantId().getTenantDate());
|
||||||
|
|
||||||
// HFJ_RES_VER
|
// HFJ_RES_VER
|
||||||
ResourceHistoryTable resVer = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 2);
|
int version = 2;
|
||||||
assertEquals(tenantId, resVer.getTenantId().getTenantId().intValue());
|
ResourceHistoryTable resVer = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, version);
|
||||||
assertEquals(tenantDate, resVer.getTenantId().getTenantDate());
|
assertEquals(myTenantId, resVer.getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, resVer.getTenantId().getTenantDate());
|
||||||
|
|
||||||
|
// HFJ_RES_VER_PROV
|
||||||
|
assertNotNull(resVer.getProvenance());
|
||||||
|
assertNotNull(resVer.getTenantId());
|
||||||
|
assertEquals(myTenantId, resVer.getProvenance().getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, resVer.getProvenance().getTenantId().getTenantDate());
|
||||||
|
|
||||||
|
// HFJ_SPIDX_STRING
|
||||||
|
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
|
||||||
|
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
|
||||||
|
assertEquals(10, strings.size());
|
||||||
|
assertEquals(myTenantId, strings.get(0).getTenantId().getTenantId().intValue());
|
||||||
|
assertEquals(myTenantDate, strings.get(0).getTenantId().getTenantDate());
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadAcrossTenants() {
|
||||||
|
IIdType patientId1 = createPatient(1, withActiveTrue());
|
||||||
|
IIdType patientId2 = createPatient(1, withActiveTrue());
|
||||||
|
|
||||||
|
IdType gotId1 = myPatientDao.read(patientId1, mySrd).getIdElement().toUnqualifiedVersionless();
|
||||||
|
assertEquals(patientId1, gotId1);
|
||||||
|
IdType gotId2 = myPatientDao.read(patientId2, mySrd).getIdElement().toUnqualifiedVersionless();
|
||||||
|
assertEquals(patientId2, gotId2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchAcrossAllTenants() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void createUniqueCompositeSp() {
|
private void createUniqueCompositeSp() {
|
||||||
SearchParameter sp = new SearchParameter();
|
SearchParameter sp = new SearchParameter();
|
||||||
sp.setId("SearchParameter/patient-birthdate");
|
sp.setId("SearchParameter/patient-birthdate");
|
||||||
|
@ -171,7 +263,7 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
mySearchParameterDao.update(sp);
|
mySearchParameterDao.update(sp);
|
||||||
|
|
||||||
sp = new SearchParameter();
|
sp = new SearchParameter();
|
||||||
sp.setId("SearchParameter/patient-birthdate");
|
sp.setId("SearchParameter/patient-birthdate-unique");
|
||||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||||
sp.addBase("Patient");
|
sp.addBase("Patient");
|
||||||
|
@ -186,27 +278,48 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||||
mySearchParamRegistry.forceRefresh();
|
mySearchParamRegistry.forceRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTenant(int theTenantId, LocalDate theTenantDate) {
|
|
||||||
|
|
||||||
|
private void addCreateTenant(int theTenantId, LocalDate theTenantDate) {
|
||||||
if (myTenantInterceptor == null) {
|
if (myTenantInterceptor == null) {
|
||||||
myTenantInterceptor = new MyInterceptor();
|
myTenantInterceptor = new MyInterceptor();
|
||||||
myInterceptorRegistry.registerInterceptor(myInterceptor);
|
myInterceptorRegistry.registerInterceptor(myTenantInterceptor);
|
||||||
}
|
}
|
||||||
myTenantInterceptor.addTenant(new TenantId(theTenantId, theTenantDate));
|
myTenantInterceptor.addCreateTenant(new TenantId(theTenantId, theTenantDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IIdType createPatient(int theTenantId, Consumer<Patient>... theModifiers) {
|
||||||
|
addCreateTenant(theTenantId, null);
|
||||||
|
Patient p = new Patient();
|
||||||
|
for (Consumer<Patient> next : theModifiers) {
|
||||||
|
next.accept(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createRequestId() {
|
||||||
|
when(mySrd.getRequestId()).thenReturn("REQUEST_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<Patient> withActiveTrue() {
|
||||||
|
return t->t.setActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Interceptor
|
@Interceptor
|
||||||
public static class MyInterceptor {
|
public static class MyInterceptor {
|
||||||
|
|
||||||
private final List<TenantId> myTenantIds = new ArrayList<>();
|
|
||||||
|
|
||||||
public void addTenant(TenantId theTenantId) {
|
private final List<TenantId> myCreateTenantIds = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addCreateTenant(TenantId theTenantId) {
|
||||||
Validate.notNull(theTenantId);
|
Validate.notNull(theTenantId);
|
||||||
myTenantIds.add(theTenantId);
|
myCreateTenantIds.add(theTenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Hook(Pointcut.STORAGE_TENANT_IDENTIFY_CREATE)
|
@Hook(Pointcut.STORAGE_TENANT_IDENTIFY_CREATE)
|
||||||
public TenantId tenantIdentifyCreate() {
|
public TenantId tenantIdentifyCreate() {
|
||||||
TenantId retVal = myTenantIds.remove(0);
|
TenantId retVal = myCreateTenantIds.remove(0);
|
||||||
ourLog.info("Returning tenant ID: {}", retVal);
|
ourLog.info("Returning tenant ID: {}", retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
||||||
version.onTable("HFJ_RES_VER").modifyColumn("20200220.1", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
version.onTable("HFJ_RES_VER").modifyColumn("20200220.1", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||||
|
|
||||||
// Add mlutiitenancy
|
// Add mlutiitenancy
|
||||||
version.onTable("HFJ_RESOURCE").dropColumn("20200327.1", "RES_PROFILE");
|
version.onTable("HFJ_RESOURCE").dropIndex("20200327.1", "IDX_RES_PROFILE");
|
||||||
|
version.onTable("HFJ_RESOURCE").dropColumn("20200327.2", "RES_PROFILE");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void init420() { // 20191015 - 20200217
|
protected void init420() { // 20191015 - 20200217
|
||||||
|
|
|
@ -62,6 +62,8 @@ public class ForcedId {
|
||||||
@ColumnDefault("''")
|
@ColumnDefault("''")
|
||||||
@Column(name = "RESOURCE_TYPE", nullable = true, length = 100, updatable = true)
|
@Column(name = "RESOURCE_TYPE", nullable = true, length = 100, updatable = true)
|
||||||
private String myResourceType;
|
private String myResourceType;
|
||||||
|
@Embedded
|
||||||
|
private TenantId myTenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -93,4 +95,12 @@ public class ForcedId {
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return myId;
|
return myId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TenantId getTenantId() {
|
||||||
|
return myTenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(TenantId theTenantId) {
|
||||||
|
myTenantId = theTenantId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,18 +51,17 @@ public class ResourceHistoryProvenanceEntity {
|
||||||
@Embedded
|
@Embedded
|
||||||
private TenantId myTenantId;
|
private TenantId myTenantId;
|
||||||
|
|
||||||
public ResourceTable getResourceTable() {
|
/**
|
||||||
return myResourceTable;
|
* Constructor
|
||||||
|
*/
|
||||||
|
public ResourceHistoryProvenanceEntity() {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResourceTable(ResourceTable theResourceTable) {
|
public void setResourceTable(ResourceTable theResourceTable) {
|
||||||
myResourceTable = theResourceTable;
|
myResourceTable = theResourceTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceHistoryTable getResourceHistoryTable() {
|
|
||||||
return myResourceHistoryTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResourceHistoryTable(ResourceHistoryTable theResourceHistoryTable) {
|
public void setResourceHistoryTable(ResourceHistoryTable theResourceHistoryTable) {
|
||||||
myResourceHistoryTable = theResourceHistoryTable;
|
myResourceHistoryTable = theResourceHistoryTable;
|
||||||
}
|
}
|
||||||
|
@ -86,4 +85,12 @@ public class ResourceHistoryProvenanceEntity {
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return myId;
|
return myId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TenantId getTenantId() {
|
||||||
|
return myTenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(TenantId theTenantId) {
|
||||||
|
myTenantId = theTenantId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class ResourceIndexedCompositeStringUnique implements Comparable<Resource
|
||||||
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString) {
|
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString) {
|
||||||
setResource(theResource);
|
setResource(theResource);
|
||||||
setIndexString(theIndexString);
|
setIndexString(theIndexString);
|
||||||
|
setTenantId(theResource.getTenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TenantId getTenantId() {
|
public TenantId getTenantId() {
|
||||||
|
|
|
@ -183,9 +183,10 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
|
||||||
public String toString() {
|
public String toString() {
|
||||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||||
b.append("paramName", getParamName());
|
b.append("paramName", getParamName());
|
||||||
b.append("resourceId", getResource().getId()); // TODO: add a field so we don't need to resolve this
|
b.append("resourceId", getResourcePid());
|
||||||
b.append("valueLow", new InstantDt(getValueLow()));
|
b.append("valueLow", new InstantDt(getValueLow()));
|
||||||
b.append("valueHigh", new InstantDt(getValueHigh()));
|
b.append("valueHigh", new InstantDt(getValueHigh()));
|
||||||
|
b.append("missing", isMissing());
|
||||||
return b.build();
|
return b.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
@Table(name = "HFJ_RESOURCE", uniqueConstraints = {}, indexes = {
|
@Table(name = "HFJ_RESOURCE", uniqueConstraints = {}, indexes = {
|
||||||
@Index(name = "IDX_RES_DATE", columnList = "RES_UPDATED"),
|
@Index(name = "IDX_RES_DATE", columnList = "RES_UPDATED"),
|
||||||
@Index(name = "IDX_RES_LANG", columnList = "RES_TYPE,RES_LANGUAGE"),
|
@Index(name = "IDX_RES_LANG", columnList = "RES_TYPE,RES_LANGUAGE"),
|
||||||
@Index(name = "IDX_RES_PROFILE", columnList = "RES_PROFILE"),
|
|
||||||
@Index(name = "IDX_RES_TYPE", columnList = "RES_TYPE"),
|
@Index(name = "IDX_RES_TYPE", columnList = "RES_TYPE"),
|
||||||
@Index(name = "IDX_INDEXSTATUS", columnList = "SP_INDEX_STATUS")
|
@Index(name = "IDX_INDEXSTATUS", columnList = "SP_INDEX_STATUS")
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue