Make sure we don't update unchanged resources in a transaction
This commit is contained in:
parent
d550392047
commit
20c14fe8a6
|
@ -1508,6 +1508,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
||||||
if (theResource != null) {
|
if (theResource != null) {
|
||||||
populateResourceIdFromEntity(theEntity, theResource);
|
populateResourceIdFromEntity(theEntity, theResource);
|
||||||
}
|
}
|
||||||
|
theEntity.setUnchangedInCurrentOperation(true);
|
||||||
return theEntity;
|
return theEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1127,7 +1127,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
* we'll manually increase the version. This is important because we want the updated version number
|
* we'll manually increase the version. This is important because we want the updated version number
|
||||||
* to be reflected in the resource shared with interceptors
|
* to be reflected in the resource shared with interceptors
|
||||||
*/
|
*/
|
||||||
if (!thePerformIndexing) {
|
if (!thePerformIndexing && !savedEntity.isUnchangedInCurrentOperation()) {
|
||||||
if (resourceId.hasVersionIdPart() == false) {
|
if (resourceId.hasVersionIdPart() == false) {
|
||||||
resourceId = resourceId.withVersion(Long.toString(savedEntity.getVersion()));
|
resourceId = resourceId.withVersion(Long.toString(savedEntity.getVersion()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
||||||
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
|
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
|
||||||
private Set<ResourceTag> myTags;
|
private Set<ResourceTag> myTags;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private transient boolean myUnchangedInCurrentOperation;
|
||||||
|
|
||||||
@Column(name = "RES_VER")
|
@Column(name = "RES_VER")
|
||||||
private long myVersion;
|
private long myVersion;
|
||||||
|
|
||||||
|
@ -398,6 +401,14 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
||||||
return myParamsUriPopulated;
|
return myParamsUriPopulated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient (not saved in DB) flag indicating that this resource was found to be unchanged by the current operation
|
||||||
|
* and was not re-saved in the database
|
||||||
|
*/
|
||||||
|
public boolean isUnchangedInCurrentOperation() {
|
||||||
|
return myUnchangedInCurrentOperation;
|
||||||
|
}
|
||||||
|
|
||||||
public void setContentTextParsedIntoWords(String theContentText) {
|
public void setContentTextParsedIntoWords(String theContentText) {
|
||||||
myContentText = theContentText;
|
myContentText = theContentText;
|
||||||
}
|
}
|
||||||
|
@ -532,6 +543,14 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
||||||
myResourceType = theResourceType;
|
myResourceType = theResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient (not saved in DB) flag indicating that this resource was found to be unchanged by the current operation
|
||||||
|
* and was not re-saved in the database
|
||||||
|
*/
|
||||||
|
public void setUnchangedInCurrentOperation(boolean theUnchangedInCurrentOperation) {
|
||||||
|
myUnchangedInCurrentOperation = theUnchangedInCurrentOperation;
|
||||||
|
}
|
||||||
|
|
||||||
public void setVersion(long theVersion) {
|
public void setVersion(long theVersion) {
|
||||||
myVersion = theVersion;
|
myVersion = theVersion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,23 +23,59 @@ import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.ArrayList;
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
import org.hl7.fhir.dstu3.model.Age;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||||
|
import org.hl7.fhir.dstu3.model.CarePlan;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
import org.hl7.fhir.dstu3.model.CompartmentDefinition;
|
||||||
|
import org.hl7.fhir.dstu3.model.ConceptMap;
|
||||||
|
import org.hl7.fhir.dstu3.model.Condition;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Device;
|
||||||
|
import org.hl7.fhir.dstu3.model.DiagnosticReport;
|
||||||
|
import org.hl7.fhir.dstu3.model.Encounter;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
|
import org.hl7.fhir.dstu3.model.NamingSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.Observation;
|
||||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.OperationDefinition;
|
||||||
|
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity;
|
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity;
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType;
|
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Organization;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Period;
|
||||||
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity.QuantityComparator;
|
import org.hl7.fhir.dstu3.model.Quantity.QuantityComparator;
|
||||||
|
import org.hl7.fhir.dstu3.model.Questionnaire;
|
||||||
|
import org.hl7.fhir.dstu3.model.Range;
|
||||||
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
|
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.dstu3.model.Timing;
|
||||||
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -49,14 +85,22 @@ import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.*;
|
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.*;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.entity.*;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||||
|
@ -67,10 +111,21 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.*;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
|
@ -258,7 +313,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
TransactionTemplate tx = new TransactionTemplate(myTxManager);
|
TransactionTemplate tx = new TransactionTemplate(myTxManager);
|
||||||
tx.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
tx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||||
tx.execute(new TransactionCallbackWithoutResult() {
|
tx.execute(new TransactionCallbackWithoutResult() {
|
||||||
@Override
|
@Override
|
||||||
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
||||||
|
@ -593,15 +648,15 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
* If any of this ever fails, it means that one of the OperationOutcome issue severity codes has changed code value across versions. We store the string as a constant, so something will need to
|
* If any of this ever fails, it means that one of the OperationOutcome issue severity codes has changed code value across versions. We store the string as a constant, so something will need to
|
||||||
* be fixed.
|
* be fixed.
|
||||||
*/
|
*/
|
||||||
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR);
|
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
|
||||||
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.ERROR.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR);
|
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.ERROR.getCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
|
||||||
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR);
|
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
|
||||||
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_INFO);
|
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
|
||||||
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.INFORMATION.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_INFO);
|
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.INFORMATION.getCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
|
||||||
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_INFO);
|
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
|
||||||
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_WARN);
|
assertEquals(org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
|
||||||
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.WARNING.getCode(), BaseHapiFhirResourceDao.OO_SEVERITY_WARN);
|
assertEquals(ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum.WARNING.getCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
|
||||||
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_WARN);
|
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2010,7 +2065,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
* See #534
|
* See #534
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testLogicalReferencesAreSearchable() throws IOException {
|
public void testLogicalReferencesAreSearchable() {
|
||||||
myDaoConfig.setTreatReferencesAsLogical(null);
|
myDaoConfig.setTreatReferencesAsLogical(null);
|
||||||
myDaoConfig.addTreatReferencesAsLogical("http://foo.com/identifier*");
|
myDaoConfig.addTreatReferencesAsLogical("http://foo.com/identifier*");
|
||||||
|
|
||||||
|
@ -2288,7 +2343,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadForcedIdVersionHistory() throws InterruptedException {
|
public void testReadForcedIdVersionHistory() {
|
||||||
Patient p1 = new Patient();
|
Patient p1 = new Patient();
|
||||||
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
|
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
|
||||||
p1.setId("testReadVorcedIdVersionHistory");
|
p1.setId("testReadVorcedIdVersionHistory");
|
||||||
|
@ -2809,21 +2864,21 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
pm = new SearchParameterMap();
|
pm = new SearchParameterMap();
|
||||||
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
||||||
pm.setSort(new SortSpec(BaseResource.SP_RES_ID));
|
pm.setSort(new SortSpec(IAnyResource.SP_RES_ID));
|
||||||
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
||||||
assertEquals(5, actual.size());
|
assertEquals(5, actual.size());
|
||||||
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
|
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
|
||||||
|
|
||||||
pm = new SearchParameterMap();
|
pm = new SearchParameterMap();
|
||||||
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
||||||
pm.setSort(new SortSpec(BaseResource.SP_RES_ID).setOrder(SortOrderEnum.ASC));
|
pm.setSort(new SortSpec(IAnyResource.SP_RES_ID).setOrder(SortOrderEnum.ASC));
|
||||||
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
||||||
assertEquals(5, actual.size());
|
assertEquals(5, actual.size());
|
||||||
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
|
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
|
||||||
|
|
||||||
pm = new SearchParameterMap();
|
pm = new SearchParameterMap();
|
||||||
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
|
||||||
pm.setSort(new SortSpec(BaseResource.SP_RES_ID).setOrder(SortOrderEnum.DESC));
|
pm.setSort(new SortSpec(IAnyResource.SP_RES_ID).setOrder(SortOrderEnum.DESC));
|
||||||
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
|
||||||
assertEquals(5, actual.size());
|
assertEquals(5, actual.size());
|
||||||
assertThat(actual, contains(id4, id3, id2, id1, idMethodName));
|
assertThat(actual, contains(id4, id3, id2, id1, idMethodName));
|
||||||
|
@ -3218,13 +3273,13 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
SearchParameterMap map;
|
SearchParameterMap map;
|
||||||
|
|
||||||
map = new SearchParameterMap();
|
map = new SearchParameterMap();
|
||||||
map.add(BaseResource.SP_RES_ID, new StringParam(id1.getIdPart()));
|
map.add(IAnyResource.SP_RES_ID, new StringParam(id1.getIdPart()));
|
||||||
map.setLastUpdated(new DateRangeParam("2001", "2003"));
|
map.setLastUpdated(new DateRangeParam("2001", "2003"));
|
||||||
map.setSort(new SortSpec(Constants.PARAM_LASTUPDATED));
|
map.setSort(new SortSpec(Constants.PARAM_LASTUPDATED));
|
||||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
|
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
|
||||||
|
|
||||||
map = new SearchParameterMap();
|
map = new SearchParameterMap();
|
||||||
map.add(BaseResource.SP_RES_ID, new StringParam(id1.getIdPart()));
|
map.add(IAnyResource.SP_RES_ID, new StringParam(id1.getIdPart()));
|
||||||
map.setLastUpdated(new DateRangeParam("2001", "2003"));
|
map.setLastUpdated(new DateRangeParam("2001", "2003"));
|
||||||
map.setSort(new SortSpec(Patient.SP_NAME));
|
map.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
|
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
|
||||||
|
@ -3361,7 +3416,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||||
assertEquals("Kittens", published.get(1).getDisplay());
|
assertEquals("Kittens", published.get(1).getDisplay());
|
||||||
assertEquals("http://foo", published.get(1).getSystem());
|
assertEquals("http://foo", published.get(1).getSystem());
|
||||||
|
|
||||||
secLabels = (ArrayList<Coding>) retrieved.getMeta().getSecurity();
|
secLabels = retrieved.getMeta().getSecurity();
|
||||||
sortCodings(secLabels);
|
sortCodings(secLabels);
|
||||||
assertEquals(2, secLabels.size());
|
assertEquals(2, secLabels.size());
|
||||||
assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
|
assertEquals("seclabel:sys:1", secLabels.get(0).getSystemElement().getValue());
|
||||||
|
|
|
@ -46,19 +46,130 @@ import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3UpdateTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3UpdateTest.class);
|
||||||
|
|
||||||
@AfterClass
|
@Test
|
||||||
public static void afterClassClearContext() {
|
public void testCreateAndUpdateWithoutRequest() throws Exception {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
String methodName = "testUpdateByUrl";
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
||||||
|
IIdType id = myPatientDao.create(p).getId().toUnqualified();
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
||||||
|
p.setActive(true);
|
||||||
|
IIdType id2 = myPatientDao.create(p, "Patient?identifier=urn:system|" + methodName + "2").getId().toUnqualified();
|
||||||
|
assertEquals(id.getValue(), id2.getValue());
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId(id);
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
||||||
|
p.setActive(false);
|
||||||
|
myPatientDao.update(p).getId();
|
||||||
|
|
||||||
|
p.setActive(true);
|
||||||
|
id2 = myPatientDao.update(p, "Patient?identifier=urn:system|" + methodName + "2").getId().toUnqualified();
|
||||||
|
assertEquals(id.getIdPart(), id2.getIdPart());
|
||||||
|
assertEquals("3", id2.getVersionIdPart());
|
||||||
|
|
||||||
|
Patient newPatient = myPatientDao.read(id);
|
||||||
|
assertEquals("1", newPatient.getIdElement().getVersionIdPart());
|
||||||
|
|
||||||
|
newPatient = myPatientDao.read(id.toVersionless());
|
||||||
|
assertEquals("3", newPatient.getIdElement().getVersionIdPart());
|
||||||
|
|
||||||
|
myPatientDao.delete(id.toVersionless());
|
||||||
|
|
||||||
|
try {
|
||||||
|
myPatientDao.read(id.toVersionless());
|
||||||
|
fail();
|
||||||
|
} catch (ResourceGoneException e) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateProfilesIgnored() {
|
||||||
|
String name = "testDuplicateProfilesIgnored";
|
||||||
|
IIdType id;
|
||||||
|
{
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addName().setFamily(name);
|
||||||
|
|
||||||
|
List<IdType> tl = new ArrayList<IdType>();
|
||||||
|
tl.add(new IdType("http://foo/bar"));
|
||||||
|
tl.add(new IdType("http://foo/bar"));
|
||||||
|
tl.add(new IdType("http://foo/bar"));
|
||||||
|
patient.getMeta().getProfile().addAll(tl);
|
||||||
|
|
||||||
|
id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a read
|
||||||
|
{
|
||||||
|
Patient patient = myPatientDao.read(id, mySrd);
|
||||||
|
List<UriType> tl = patient.getMeta().getProfile();
|
||||||
|
assertEquals(1, tl.size());
|
||||||
|
assertEquals("http://foo/bar", tl.get(0).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleUpdatesWithNoChangesDoesNotResultInAnUpdateForDiscreteUpdates() {
|
||||||
|
|
||||||
|
// First time
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
p.setId("Patient/A");
|
||||||
|
String id = myPatientDao.update(p).getId().getValue();
|
||||||
|
assertThat(id, endsWith("Patient/A/_history/1"));
|
||||||
|
|
||||||
|
// Second time should not result in an update
|
||||||
|
p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
p.setId("Patient/A");
|
||||||
|
id = myPatientDao.update(p).getId().getValue();
|
||||||
|
assertThat(id, endsWith("Patient/A/_history/1"));
|
||||||
|
|
||||||
|
// And third time should not result in an update
|
||||||
|
p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
p.setId("Patient/A");
|
||||||
|
id = myPatientDao.update(p).getId().getValue();
|
||||||
|
assertThat(id, endsWith("Patient/A/_history/1"));
|
||||||
|
|
||||||
|
myPatientDao.read(new IdType("Patient/A"));
|
||||||
|
myPatientDao.read(new IdType("Patient/A/_history/1"));
|
||||||
|
try {
|
||||||
|
myPatientDao.read(new IdType("Patient/A/_history/2"));
|
||||||
|
fail();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
myPatientDao.read(new IdType("Patient/A/_history/3"));
|
||||||
|
fail();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create one more
|
||||||
|
p = new Patient();
|
||||||
|
p.setActive(false);
|
||||||
|
p.setId("Patient/A");
|
||||||
|
id = myPatientDao.update(p).getId().getValue();
|
||||||
|
assertThat(id, endsWith("Patient/A/_history/2"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateAndGetHistoryResource() throws InterruptedException {
|
public void testUpdateAndGetHistoryResource() throws InterruptedException {
|
||||||
|
@ -113,14 +224,14 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
IBundleProvider historyBundle = myPatientDao.history(outcome.getId(), null, null, mySrd);
|
IBundleProvider historyBundle = myPatientDao.history(outcome.getId(), null, null, mySrd);
|
||||||
|
|
||||||
assertEquals(2, historyBundle.size().intValue());
|
assertEquals(2, historyBundle.size().intValue());
|
||||||
|
|
||||||
List<IBaseResource> history = historyBundle.getResources(0, 2);
|
List<IBaseResource> history = historyBundle.getResources(0, 2);
|
||||||
|
|
||||||
ourLog.info("updated : {}", updated.getValueAsString());
|
ourLog.info("updated : {}", updated.getValueAsString());
|
||||||
ourLog.info(" * Exp : {}", ((Resource) history.get(1)).getMeta().getLastUpdatedElement().getValueAsString());
|
ourLog.info(" * Exp : {}", ((Resource) history.get(1)).getMeta().getLastUpdatedElement().getValueAsString());
|
||||||
ourLog.info("updated2: {}", updated2.getValueAsString());
|
ourLog.info("updated2: {}", updated2.getValueAsString());
|
||||||
ourLog.info(" * Exp : {}", ((Resource) history.get(0)).getMeta().getLastUpdatedElement().getValueAsString());
|
ourLog.info(" * Exp : {}", ((Resource) history.get(0)).getMeta().getLastUpdatedElement().getValueAsString());
|
||||||
|
|
||||||
assertEquals("1", history.get(1).getIdElement().getVersionIdPart());
|
assertEquals("1", history.get(1).getIdElement().getVersionIdPart());
|
||||||
assertEquals("2", history.get(0).getIdElement().getVersionIdPart());
|
assertEquals("2", history.get(0).getIdElement().getVersionIdPart());
|
||||||
assertEquals(updated.getValueAsString(), ((Resource) history.get(1)).getMeta().getLastUpdatedElement().getValueAsString());
|
assertEquals(updated.getValueAsString(), ((Resource) history.get(1)).getMeta().getLastUpdatedElement().getValueAsString());
|
||||||
|
@ -154,49 +265,6 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateAndUpdateWithoutRequest() throws Exception {
|
|
||||||
String methodName = "testUpdateByUrl";
|
|
||||||
|
|
||||||
Patient p = new Patient();
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
|
||||||
IIdType id = myPatientDao.create(p).getId().toUnqualified();
|
|
||||||
|
|
||||||
p = new Patient();
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
|
||||||
p.setActive(true);
|
|
||||||
IIdType id2 = myPatientDao.create(p, "Patient?identifier=urn:system|" + methodName + "2").getId().toUnqualified();
|
|
||||||
assertEquals(id.getValue(), id2.getValue());
|
|
||||||
|
|
||||||
p = new Patient();
|
|
||||||
p.setId(id);
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
|
||||||
p.setActive(false);
|
|
||||||
myPatientDao.update(p).getId();
|
|
||||||
|
|
||||||
p.setActive(true);
|
|
||||||
id2 = myPatientDao.update(p, "Patient?identifier=urn:system|" + methodName + "2").getId().toUnqualified();
|
|
||||||
assertEquals(id.getIdPart(), id2.getIdPart());
|
|
||||||
assertEquals("3", id2.getVersionIdPart());
|
|
||||||
|
|
||||||
Patient newPatient = myPatientDao.read(id);
|
|
||||||
assertEquals("1", newPatient.getIdElement().getVersionIdPart());
|
|
||||||
|
|
||||||
newPatient = myPatientDao.read(id.toVersionless());
|
|
||||||
assertEquals("3", newPatient.getIdElement().getVersionIdPart());
|
|
||||||
|
|
||||||
myPatientDao.delete(id.toVersionless());
|
|
||||||
|
|
||||||
try {
|
|
||||||
myPatientDao.read(id.toVersionless());
|
|
||||||
fail();
|
|
||||||
} catch (ResourceGoneException e) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateConditionalByLastUpdated() throws Exception {
|
public void testUpdateConditionalByLastUpdated() throws Exception {
|
||||||
String methodName = "testUpdateByUrl";
|
String methodName = "testUpdateByUrl";
|
||||||
|
@ -208,7 +276,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
InstantDt start = InstantDt.withCurrentTime();
|
InstantDt start = InstantDt.withCurrentTime();
|
||||||
ourLog.info("First time: {}", start.getValueAsString());
|
ourLog.info("First time: {}", start.getValueAsString());
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
|
|
||||||
p = new Patient();
|
p = new Patient();
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||||
IIdType id = myPatientDao.create(p, mySrd).getId();
|
IIdType id = myPatientDao.create(p, mySrd).getId();
|
||||||
|
@ -237,35 +305,35 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
public void testUpdateConditionalByLastUpdatedWithWrongTimezone() throws Exception {
|
public void testUpdateConditionalByLastUpdatedWithWrongTimezone() throws Exception {
|
||||||
TimeZone def = TimeZone.getDefault();
|
TimeZone def = TimeZone.getDefault();
|
||||||
try {
|
try {
|
||||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT-0:00"));
|
TimeZone.setDefault(TimeZone.getTimeZone("GMT-0:00"));
|
||||||
String methodName = "testUpdateByUrl";
|
String methodName = "testUpdateByUrl";
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
p.addIdentifier().setSystem("urn:system").setValue(methodName + "2");
|
||||||
myPatientDao.create(p, mySrd).getId();
|
myPatientDao.create(p, mySrd).getId();
|
||||||
|
|
||||||
InstantDt start = InstantDt.withCurrentTime();
|
InstantDt start = InstantDt.withCurrentTime();
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
|
|
||||||
p = new Patient();
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
|
||||||
IIdType id = myPatientDao.create(p, mySrd).getId();
|
|
||||||
ourLog.info("Created patient, got it: {}", id);
|
|
||||||
|
|
||||||
Thread.sleep(100);
|
p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||||
|
IIdType id = myPatientDao.create(p, mySrd).getId();
|
||||||
|
ourLog.info("Created patient, got it: {}", id);
|
||||||
|
|
||||||
p = new Patient();
|
Thread.sleep(100);
|
||||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
|
||||||
p.addName().setFamily("Hello");
|
|
||||||
p.setId("Patient/" + methodName);
|
|
||||||
|
|
||||||
myPatientDao.update(p, "Patient?_lastUpdated=gt" + start.getValueAsString(), mySrd);
|
p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||||
|
p.addName().setFamily("Hello");
|
||||||
|
p.setId("Patient/" + methodName);
|
||||||
|
|
||||||
p = myPatientDao.read(id.toVersionless(), mySrd);
|
myPatientDao.update(p, "Patient?_lastUpdated=gt" + start.getValueAsString(), mySrd);
|
||||||
assertThat(p.getIdElement().toVersionless().toString(), not(containsString("test")));
|
|
||||||
assertEquals(id.toVersionless(), p.getIdElement().toVersionless());
|
p = myPatientDao.read(id.toVersionless(), mySrd);
|
||||||
assertNotEquals(id, p.getIdElement());
|
assertThat(p.getIdElement().toVersionless().toString(), not(containsString("test")));
|
||||||
assertThat(p.getIdElement().toString(), endsWith("/_history/2"));
|
assertEquals(id.toVersionless(), p.getIdElement().toVersionless());
|
||||||
|
assertNotEquals(id, p.getIdElement());
|
||||||
|
assertThat(p.getIdElement().toString(), endsWith("/_history/2"));
|
||||||
} finally {
|
} finally {
|
||||||
TimeZone.setDefault(def);
|
TimeZone.setDefault(def);
|
||||||
}
|
}
|
||||||
|
@ -296,57 +364,27 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
myPatientDao.update(p, mySrd);
|
myPatientDao.update(p, mySrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Per the spec, update should preserve tags and security labels but not profiles
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateMaintainsTagsAndSecurityLabels() throws InterruptedException {
|
@Ignore
|
||||||
String methodName = "testUpdateMaintainsTagsAndSecurityLabels";
|
public void testUpdateIgnoresIdenticalVersions() {
|
||||||
|
String methodName = "testUpdateIgnoresIdenticalVersions";
|
||||||
|
|
||||||
IIdType p1id;
|
Patient p1 = new Patient();
|
||||||
{
|
p1.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||||
Patient p1 = new Patient();
|
p1.addName().setFamily("Tester").addGiven(methodName);
|
||||||
p1.addName().setFamily(methodName);
|
IIdType p1id = myPatientDao.create(p1, mySrd).getId();
|
||||||
|
|
||||||
p1.getMeta().addTag("tag_scheme1", "tag_term1",null);
|
|
||||||
p1.getMeta().addSecurity("sec_scheme1", "sec_term1",null);
|
|
||||||
p1.getMeta().addProfile("http://foo1");
|
|
||||||
|
|
||||||
p1id = myPatientDao.create(p1, mySrd).getId().toUnqualifiedVersionless();
|
IIdType p1id2 = myPatientDao.update(p1, mySrd).getId();
|
||||||
}
|
assertEquals(p1id.getValue(), p1id2.getValue());
|
||||||
{
|
|
||||||
Patient p1 = new Patient();
|
|
||||||
p1.setId(p1id);
|
|
||||||
p1.addName().setFamily(methodName);
|
|
||||||
|
|
||||||
p1.getMeta().addTag("tag_scheme2", "tag_term2", null);
|
p1.addName().addGiven("NewGiven");
|
||||||
p1.getMeta().addSecurity("sec_scheme2", "sec_term2", null);
|
IIdType p1id3 = myPatientDao.update(p1, mySrd).getId();
|
||||||
p1.getMeta().addProfile("http://foo2");
|
assertNotEquals(p1id.getValue(), p1id3.getValue());
|
||||||
|
|
||||||
myPatientDao.update(p1, mySrd);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Patient p1 = myPatientDao.read(p1id, mySrd);
|
|
||||||
List<Coding> tagList = p1.getMeta().getTag();
|
|
||||||
Set<String> secListValues = new HashSet<String>();
|
|
||||||
for (Coding next : tagList) {
|
|
||||||
secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue());
|
|
||||||
}
|
|
||||||
assertThat(secListValues, containsInAnyOrder("tag_scheme1|tag_term1", "tag_scheme2|tag_term2"));
|
|
||||||
List<Coding> secList = p1.getMeta().getSecurity();
|
|
||||||
secListValues = new HashSet<String>();
|
|
||||||
for (Coding next : secList) {
|
|
||||||
secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue());
|
|
||||||
}
|
|
||||||
assertThat(secListValues, containsInAnyOrder("sec_scheme1|sec_term1", "sec_scheme2|sec_term2"));
|
|
||||||
List<UriType> profileList = p1.getMeta().getProfile();
|
|
||||||
assertEquals(1, profileList.size());
|
|
||||||
assertEquals("http://foo2", profileList.get(0).getValueAsString()); // no foo1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateMaintainsSearchParams() throws InterruptedException {
|
public void testUpdateMaintainsSearchParams() {
|
||||||
Patient p1 = new Patient();
|
Patient p1 = new Patient();
|
||||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2AAA");
|
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2AAA");
|
||||||
p1.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2AAA");
|
p1.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2AAA");
|
||||||
|
@ -381,77 +419,53 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per the spec, update should preserve tags and security labels but not profiles
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
|
public void testUpdateMaintainsTagsAndSecurityLabels() {
|
||||||
Patient p1 = new Patient();
|
String methodName = "testUpdateMaintainsTagsAndSecurityLabels";
|
||||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
|
||||||
p1.addName().setFamily("Tester").addGiven("testUpdateRejectsInvalidTypes");
|
|
||||||
IIdType p1id = myPatientDao.create(p1, mySrd).getId();
|
|
||||||
|
|
||||||
Organization p2 = new Organization();
|
IIdType p1id;
|
||||||
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
|
|
||||||
try {
|
|
||||||
p2.setId(new IdType("Organization/" + p1id.getIdPart()));
|
|
||||||
myOrganizationDao.update(p2, mySrd);
|
|
||||||
fail();
|
|
||||||
} catch (UnprocessableEntityException e) {
|
|
||||||
// good
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
p2.setId(new IdType("Patient/" + p1id.getIdPart()));
|
|
||||||
myOrganizationDao.update(p2, mySrd);
|
|
||||||
fail();
|
|
||||||
} catch (UnprocessableEntityException e) {
|
|
||||||
ourLog.error("Good", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testUpdateIgnoresIdenticalVersions() throws InterruptedException {
|
|
||||||
String methodName = "testUpdateIgnoresIdenticalVersions";
|
|
||||||
|
|
||||||
Patient p1 = new Patient();
|
|
||||||
p1.addIdentifier().setSystem("urn:system").setValue(methodName);
|
|
||||||
p1.addName().setFamily("Tester").addGiven(methodName);
|
|
||||||
IIdType p1id = myPatientDao.create(p1, mySrd).getId();
|
|
||||||
|
|
||||||
IIdType p1id2 = myPatientDao.update(p1, mySrd).getId();
|
|
||||||
assertEquals(p1id.getValue(), p1id2.getValue());
|
|
||||||
|
|
||||||
p1.addName().addGiven("NewGiven");
|
|
||||||
IIdType p1id3 = myPatientDao.update(p1, mySrd).getId();
|
|
||||||
assertNotEquals(p1id.getValue(), p1id3.getValue());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDuplicateProfilesIgnored() {
|
|
||||||
String name = "testDuplicateProfilesIgnored";
|
|
||||||
IIdType id;
|
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient p1 = new Patient();
|
||||||
patient.addName().setFamily(name);
|
p1.addName().setFamily(methodName);
|
||||||
|
|
||||||
List<IdType> tl = new ArrayList<IdType>();
|
p1.getMeta().addTag("tag_scheme1", "tag_term1", null);
|
||||||
tl.add(new IdType("http://foo/bar"));
|
p1.getMeta().addSecurity("sec_scheme1", "sec_term1", null);
|
||||||
tl.add(new IdType("http://foo/bar"));
|
p1.getMeta().addProfile("http://foo1");
|
||||||
tl.add(new IdType("http://foo/bar"));
|
|
||||||
patient.getMeta().getProfile().addAll(tl);
|
|
||||||
|
|
||||||
id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
p1id = myPatientDao.create(p1, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a read
|
|
||||||
{
|
{
|
||||||
Patient patient = myPatientDao.read(id, mySrd);
|
Patient p1 = new Patient();
|
||||||
List<UriType> tl = patient.getMeta().getProfile();
|
p1.setId(p1id);
|
||||||
assertEquals(1, tl.size());
|
p1.addName().setFamily(methodName);
|
||||||
assertEquals("http://foo/bar", tl.get(0).getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
p1.getMeta().addTag("tag_scheme2", "tag_term2", null);
|
||||||
|
p1.getMeta().addSecurity("sec_scheme2", "sec_term2", null);
|
||||||
|
p1.getMeta().addProfile("http://foo2");
|
||||||
|
|
||||||
|
myPatientDao.update(p1, mySrd);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Patient p1 = myPatientDao.read(p1id, mySrd);
|
||||||
|
List<Coding> tagList = p1.getMeta().getTag();
|
||||||
|
Set<String> secListValues = new HashSet<String>();
|
||||||
|
for (Coding next : tagList) {
|
||||||
|
secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue());
|
||||||
|
}
|
||||||
|
assertThat(secListValues, containsInAnyOrder("tag_scheme1|tag_term1", "tag_scheme2|tag_term2"));
|
||||||
|
List<Coding> secList = p1.getMeta().getSecurity();
|
||||||
|
secListValues = new HashSet<String>();
|
||||||
|
for (Coding next : secList) {
|
||||||
|
secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue());
|
||||||
|
}
|
||||||
|
assertThat(secListValues, containsInAnyOrder("sec_scheme1|sec_term1", "sec_scheme2|sec_term2"));
|
||||||
|
List<UriType> profileList = p1.getMeta().getProfile();
|
||||||
|
assertEquals(1, profileList.size());
|
||||||
|
assertEquals("http://foo2", profileList.get(0).getValueAsString()); // no foo1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -501,6 +515,33 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateRejectsInvalidTypes() {
|
||||||
|
Patient p1 = new Patient();
|
||||||
|
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
||||||
|
p1.addName().setFamily("Tester").addGiven("testUpdateRejectsInvalidTypes");
|
||||||
|
IIdType p1id = myPatientDao.create(p1, mySrd).getId();
|
||||||
|
|
||||||
|
Organization p2 = new Organization();
|
||||||
|
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
|
||||||
|
try {
|
||||||
|
p2.setId(new IdType("Organization/" + p1id.getIdPart()));
|
||||||
|
myOrganizationDao.update(p2, mySrd);
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
p2.setId(new IdType("Patient/" + p1id.getIdPart()));
|
||||||
|
myOrganizationDao.update(p2, mySrd);
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
ourLog.error("Good", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateUnknownNumericIdFails() {
|
public void testUpdateUnknownNumericIdFails() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -529,63 +570,10 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateWithNumericIdFails() {
|
|
||||||
Patient p = new Patient();
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
|
||||||
p.addName().setFamily("Hello");
|
|
||||||
p.setId("Patient/123");
|
|
||||||
try {
|
|
||||||
myPatientDao.update(p, mySrd);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertThat(e.getMessage(), containsString("clients may only assign IDs which contain at least one non-numeric"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateWithNumericThenTextIdSucceeds() {
|
|
||||||
Patient p = new Patient();
|
|
||||||
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
|
||||||
p.addName().setFamily("Hello");
|
|
||||||
p.setId("Patient/123abc");
|
|
||||||
IIdType id = myPatientDao.update(p, mySrd).getId();
|
|
||||||
assertEquals("123abc", id.getIdPart());
|
|
||||||
assertEquals("1", id.getVersionIdPart());
|
|
||||||
|
|
||||||
p = myPatientDao.read(id.toUnqualifiedVersionless(), mySrd);
|
|
||||||
assertEquals("Patient/123abc", p.getIdElement().toUnqualifiedVersionless().getValue());
|
|
||||||
assertEquals("Hello", p.getName().get(0).getFamily());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateWithNoChangeDetectionUpdateUnchanged() {
|
|
||||||
String name = "testUpdateUnchanged";
|
|
||||||
IIdType id1, id2;
|
|
||||||
{
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.addName().setFamily(name);
|
|
||||||
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualified();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update
|
|
||||||
{
|
|
||||||
Patient patient = new Patient();
|
|
||||||
patient.setId(id1);
|
|
||||||
patient.addName().setFamily(name);
|
|
||||||
id2 = myPatientDao.update(patient, mySrd).getId().toUnqualified();
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(id1.getValue(), id2.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWithNoChangeDetectionDisabledUpdateUnchanged() {
|
public void testUpdateWithNoChangeDetectionDisabledUpdateUnchanged() {
|
||||||
myDaoConfig.setSuppressUpdatesWithNoChange(false);
|
myDaoConfig.setSuppressUpdatesWithNoChange(false);
|
||||||
|
|
||||||
String name = "testUpdateUnchanged";
|
String name = "testUpdateUnchanged";
|
||||||
IIdType id1, id2;
|
IIdType id1, id2;
|
||||||
{
|
{
|
||||||
|
@ -626,7 +614,39 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
assertNotEquals(id1.getValue(), id2.getValue());
|
assertNotEquals(id1.getValue(), id2.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithNoChangeDetectionUpdateTagMetaRemoved() {
|
||||||
|
String name = "testUpdateUnchanged";
|
||||||
|
IIdType id1, id2;
|
||||||
|
{
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.getMeta().addTag().setCode("CODE");
|
||||||
|
patient.addName().setFamily(name);
|
||||||
|
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualified();
|
||||||
|
}
|
||||||
|
|
||||||
|
Meta meta = new Meta();
|
||||||
|
meta.addTag().setCode("CODE");
|
||||||
|
myPatientDao.metaDeleteOperation(id1, meta, null);
|
||||||
|
|
||||||
|
meta = myPatientDao.metaGetOperation(Meta.class, id1, null);
|
||||||
|
assertEquals(0, meta.getTag().size());
|
||||||
|
|
||||||
|
// Update
|
||||||
|
{
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId(id1);
|
||||||
|
patient.addName().setFamily(name);
|
||||||
|
id2 = myPatientDao.update(patient, mySrd).getId().toUnqualified();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(id1.getValue(), id2.getValue());
|
||||||
|
|
||||||
|
meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
||||||
|
assertEquals(0, meta.getTag().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWithNoChangeDetectionUpdateTagNoChange() {
|
public void testUpdateWithNoChangeDetectionUpdateTagNoChange() {
|
||||||
String name = "testUpdateUnchanged";
|
String name = "testUpdateUnchanged";
|
||||||
|
@ -641,7 +661,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
Meta meta = new Meta();
|
Meta meta = new Meta();
|
||||||
meta.addTag().setCode("CODE");
|
meta.addTag().setCode("CODE");
|
||||||
myPatientDao.metaAddOperation(id1, meta, null);
|
myPatientDao.metaAddOperation(id1, meta, null);
|
||||||
|
|
||||||
// Update with tag
|
// Update with tag
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -652,7 +672,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(id1.getValue(), id2.getValue());
|
assertEquals(id1.getValue(), id2.getValue());
|
||||||
|
|
||||||
meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
||||||
assertEquals(1, meta.getTag().size());
|
assertEquals(1, meta.getTag().size());
|
||||||
assertEquals("CODE", meta.getTag().get(0).getCode());
|
assertEquals("CODE", meta.getTag().get(0).getCode());
|
||||||
|
@ -678,31 +698,22 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(id1.getValue(), id2.getValue());
|
assertEquals(id1.getValue(), id2.getValue());
|
||||||
|
|
||||||
Meta meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
Meta meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
||||||
assertEquals(1, meta.getTag().size());
|
assertEquals(1, meta.getTag().size());
|
||||||
assertEquals("CODE", meta.getTag().get(0).getCode());
|
assertEquals("CODE", meta.getTag().get(0).getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWithNoChangeDetectionUpdateTagMetaRemoved() {
|
public void testUpdateWithNoChangeDetectionUpdateUnchanged() {
|
||||||
String name = "testUpdateUnchanged";
|
String name = "testUpdateUnchanged";
|
||||||
IIdType id1, id2;
|
IIdType id1, id2;
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.getMeta().addTag().setCode("CODE");
|
|
||||||
patient.addName().setFamily(name);
|
patient.addName().setFamily(name);
|
||||||
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualified();
|
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualified();
|
||||||
}
|
}
|
||||||
|
|
||||||
Meta meta = new Meta();
|
|
||||||
meta.addTag().setCode("CODE");
|
|
||||||
myPatientDao.metaDeleteOperation(id1, meta, null);
|
|
||||||
|
|
||||||
|
|
||||||
meta = myPatientDao.metaGetOperation(Meta.class, id1, null);
|
|
||||||
assertEquals(0, meta.getTag().size());
|
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -712,9 +723,41 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(id1.getValue(), id2.getValue());
|
assertEquals(id1.getValue(), id2.getValue());
|
||||||
|
}
|
||||||
meta = myPatientDao.metaGetOperation(Meta.class, id2, null);
|
|
||||||
assertEquals(0, meta.getTag().size());
|
@Test
|
||||||
|
public void testUpdateWithNumericIdFails() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
||||||
|
p.addName().setFamily("Hello");
|
||||||
|
p.setId("Patient/123");
|
||||||
|
try {
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("clients may only assign IDs which contain at least one non-numeric"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithNumericThenTextIdSucceeds() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
||||||
|
p.addName().setFamily("Hello");
|
||||||
|
p.setId("Patient/123abc");
|
||||||
|
IIdType id = myPatientDao.update(p, mySrd).getId();
|
||||||
|
assertEquals("123abc", id.getIdPart());
|
||||||
|
assertEquals("1", id.getVersionIdPart());
|
||||||
|
|
||||||
|
p = myPatientDao.read(id.toUnqualifiedVersionless(), mySrd);
|
||||||
|
assertEquals("Patient/123abc", p.getIdElement().toUnqualifiedVersionless().getValue());
|
||||||
|
assertEquals("Hello", p.getName().get(0).getFamily());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -36,7 +36,15 @@
|
||||||
Search results will be cached and reused (so that if a client
|
Search results will be cached and reused (so that if a client
|
||||||
does two searches for "get me all patients matching FOO"
|
does two searches for "get me all patients matching FOO"
|
||||||
with the same FOO in short succession, we won't query the DB
|
with the same FOO in short succession, we won't query the DB
|
||||||
again but will instead reuse the cached results)
|
again but will instead reuse the cached results). Note that
|
||||||
|
this can improve performance, but does mean that searches can
|
||||||
|
return slightly out of date results. Essentially what this means
|
||||||
|
is that the latest version of individual resources will always
|
||||||
|
be returned despite this cacheing, but newly created resources
|
||||||
|
that should match may not be returned until the cache
|
||||||
|
expires. By default this cache has been set to one minute,
|
||||||
|
which should be acceptable for most real-world usage, but
|
||||||
|
this can be changed or disabled entirely.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Updates which do not actually change the contents of the resource
|
Updates which do not actually change the contents of the resource
|
||||||
|
@ -50,7 +58,8 @@
|
||||||
<code>HFJ_SEARCH_INCLUDE</code>,
|
<code>HFJ_SEARCH_INCLUDE</code>,
|
||||||
and
|
and
|
||||||
<code>HFJ_SEARCH_RESULT</code>
|
<code>HFJ_SEARCH_RESULT</code>
|
||||||
tables from your database before upgrading.
|
tables from your database before upgrading, as the structure of these tables
|
||||||
|
has changed and old search results can not be reused.
|
||||||
]]>
|
]]>
|
||||||
</action>
|
</action>
|
||||||
<action type="fix" issue="590">
|
<action type="fix" issue="590">
|
||||||
|
|
Loading…
Reference in New Issue