Implement sorting on _id and clean up create/update semantics for DSTU2

This commit is contained in:
James Agnew 2015-03-11 12:49:47 -04:00
parent b4911788a3
commit a2e562de64
7 changed files with 672 additions and 450 deletions

View File

@ -22,18 +22,29 @@ package ca.uhn.fhir.rest.gclient;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.IGenericClient;
public interface ICreateTyped extends IClientExecutable<ICreateTyped, MethodOutcome> { public interface ICreateTyped extends IClientExecutable<ICreateTyped, MethodOutcome> {
/** /**
* If you want the explicitly state an ID for your created resource, put that ID here. You generally do not * If you want the explicitly state an ID for your created resource, put that ID here. You generally do not
* need to invoke this method, so that the server will assign the ID itself. * need to invoke this method, so that the server will assign the ID itself.
*
* <p>
* Note that creating a resource by ID is no longer supported as of FHIR DSTU2. You should use the {@link IGenericClient#update()} operation
* to create-by-ID in DSTU2.
* </p>
*/ */
ICreateTyped withId(String theId); ICreateTyped withId(String theId);
/** /**
* If you want the explicitly state an ID for your created resource, put that ID here. You generally do not * If you want the explicitly state an ID for your created resource, put that ID here. You generally do not
* need to invoke this method, so that the server will assign the ID itself. * need to invoke this method, so that the server will assign the ID itself.
*
* <p>
* Note that creating a resource by ID is no longer supported as of FHIR DSTU2. You should use the {@link IGenericClient#update()} operation
* to create-by-ID in DSTU2.
* </p>
*/ */
ICreateTyped withId(IdDt theId); ICreateTyped withId(IdDt theId);

View File

@ -35,5 +35,6 @@ ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionMissingUrl=Unable to perform {0
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1} ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
ca.uhn.fhir.jpa.dao.FhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists ca.uhn.fhir.jpa.dao.FhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create entity with ID[{0}], this server does not allow clients to assign numeric IDs ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
ca.uhn.fhir.jpa.dao.FhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed. ca.uhn.fhir.jpa.dao.FhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.

View File

@ -65,6 +65,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition; import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
@ -690,16 +691,24 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
@Override @Override
public DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing) { public DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing) {
if (isNotBlank(theResource.getId().getIdPart())) {
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
if (theResource.getId().isIdPartValidLong()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
}
} else {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getId().getIdPart()));
}
}
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
}
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing) {
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
ResourceTable entity = new ResourceTable(); ResourceTable entity = new ResourceTable();
entity.setResourceType(toResourceName(theResource)); entity.setResourceType(toResourceName(theResource));
if (isNotBlank(theResource.getId().getIdPart())) {
if (theResource.getId().isIdPartValidLong()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
}
}
if (isNotBlank(theIfNoneExist)) { if (isNotBlank(theIfNoneExist)) {
Set<Long> match = processMatchUrl(theIfNoneExist, myResourceType); Set<Long> match = processMatchUrl(theIfNoneExist, myResourceType);
if (match.size() > 1) { if (match.size() > 1) {
@ -867,6 +876,20 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
return; return;
} }
if ("_id".equals(theSort.getParamName())) {
From<?, ?> forcedIdJoin = theFrom.join("myForcedId", JoinType.LEFT);
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
theOrders.add(theBuilder.asc(forcedIdJoin.get("myForcedId")));
theOrders.add(theBuilder.asc(theFrom.get("myId")));
}else {
theOrders.add(theBuilder.desc(forcedIdJoin.get("myForcedId")));
theOrders.add(theBuilder.desc(theFrom.get("myId")));
}
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, null);
return;
}
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(myResourceType); RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(myResourceType);
RuntimeSearchParam param = resourceDef.getSearchParam(theSort.getParamName()); RuntimeSearchParam param = resourceDef.getSearchParam(theSort.getParamName());
if (param == null) { if (param == null) {
@ -1632,7 +1655,14 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
if (resourceId == null || isBlank(resourceId.getIdPart())) { if (resourceId == null || isBlank(resourceId.getIdPart())) {
throw new InvalidRequestException("Can not update a resource with no ID"); throw new InvalidRequestException("Can not update a resource with no ID");
} }
entity = readEntityLatestVersion(resourceId); try {
entity = readEntityLatestVersion(resourceId);
} catch (ResourceNotFoundException e) {
if (Character.isDigit(theResource.getId().getIdPart().charAt(0))) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
}
return doCreate(theResource, null, true);
}
} }
if (resourceId.hasVersionIdPart() && resourceId.getVersionIdPartAsLong().longValue() != entity.getVersion()) { if (resourceId.hasVersionIdPart() && resourceId.getVersionIdPartAsLong().longValue() != entity.getVersion()) {

View File

@ -0,0 +1,142 @@
package ca.uhn.fhir.jpa.dao;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.hamcrest.core.StringContains;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.Device;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Encounter;
import ca.uhn.fhir.model.dstu.resource.Location;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class FhirResourceDaoDstu1Test {
private static ClassPathXmlApplicationContext ourCtx;
private static IFhirResourceDao<Device> ourDeviceDao;
private static IFhirResourceDao<DiagnosticReport> ourDiagnosticReportDao;
private static IFhirResourceDao<Encounter> ourEncounterDao;
private static FhirContext ourFhirCtx;
private static IFhirResourceDao<Location> ourLocationDao;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu1Test.class);
private static IFhirResourceDao<Observation> ourObservationDao;
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static IFhirResourceDao<Patient> ourPatientDao;
@Test
public void testCreateDuplicateIdFails() {
String methodName = "testCreateDuplocateIdFailsText";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
try {
ourPatientDao.create(p);
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Can not create entity with ID[" + methodName + "], a resource with this ID already exists"));
}
}
@Test
public void testCreateNumericIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123");
try {
ourPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("clients may only assign IDs which begin with a non-numeric"));
}
}
@Test
public void testCreateWithInvalidReferenceFailsGracefully() {
Patient patient = new Patient();
patient.addName().addFamily("testSearchResourceLinkWithChainWithMultipleTypes01");
patient.setManagingOrganization(new ResourceReferenceDt("Patient/99999999"));
try {
ourPatientDao.create(patient);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), StringContains.containsString("99999 not found"));
}
}
@Test
public void testUpdateRejectsIdWhichPointsToForcedId() throws InterruptedException {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId01");
p1.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId01");
p1.setId("ABABA");
IdDt p1id = ourPatientDao.create(p1).getId();
assertEquals("ABABA", p1id.getIdPart());
Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId02");
p2.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId02");
IdDt p2id = ourPatientDao.create(p2).getId();
long p1longId = p2id.getIdPartAsLong() - 1;
try {
ourPatientDao.read(new IdDt("Patient/" + p1longId));
fail();
} catch (ResourceNotFoundException e) {
// good
}
try {
p1.setId(new IdDt("Patient/" + p1longId));
ourPatientDao.update(p1);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("clients may only assign IDs which begin with a non-numeric"));
}
}
@AfterClass
public static void afterClass() {
ourCtx.close();
}
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() {
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
ourPatientDao = ourCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
ourObservationDao = ourCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
ourDiagnosticReportDao = ourCtx.getBean("myDiagnosticReportDaoDstu1", IFhirResourceDao.class);
ourDeviceDao = ourCtx.getBean("myDeviceDaoDstu1", IFhirResourceDao.class);
ourOrganizationDao = ourCtx.getBean("myOrganizationDaoDstu1", IFhirResourceDao.class);
ourLocationDao = ourCtx.getBean("myLocationDaoDstu1", IFhirResourceDao.class);
ourEncounterDao = ourCtx.getBean("myEncounterDaoDstu1", IFhirResourceDao.class);
ourFhirCtx = ourCtx.getBean(FhirContext.class);
}
}

View File

@ -73,7 +73,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class FhirResourceDaoTest { public class FhirResourceDaoDstu2Test {
private static ClassPathXmlApplicationContext ourCtx; private static ClassPathXmlApplicationContext ourCtx;
private static IFhirResourceDao<Device> ourDeviceDao; private static IFhirResourceDao<Device> ourDeviceDao;
@ -81,187 +81,11 @@ public class FhirResourceDaoTest {
private static IFhirResourceDao<Encounter> ourEncounterDao; private static IFhirResourceDao<Encounter> ourEncounterDao;
private static FhirContext ourFhirCtx; private static FhirContext ourFhirCtx;
private static IFhirResourceDao<Location> ourLocationDao; private static IFhirResourceDao<Location> ourLocationDao;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoTest.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2Test.class);
private static IFhirResourceDao<Observation> ourObservationDao; private static IFhirResourceDao<Observation> ourObservationDao;
private static IFhirResourceDao<Organization> ourOrganizationDao; private static IFhirResourceDao<Organization> ourOrganizationDao;
private static IFhirResourceDao<Patient> ourPatientDao; private static IFhirResourceDao<Patient> ourPatientDao;
@Test
public void testSearchValueQuantity() {
String methodName = "testSearchValueQuantity";
QuantityParam param;
Set<Long> found;
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
found = ourObservationDao.searchForIds("value-quantity", param);
int initialSize = found.size();
Observation o = new Observation();
o.getCode().addCoding().setSystem("urn:foo").setCode(methodName + "code");
QuantityDt q = new QuantityDt().setSystem("urn:bar:" + methodName).setCode(methodName + "units").setValue(100);
o.setValue(q);
ourObservationDao.create(o);
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1 + initialSize, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, methodName + "units");
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, null);
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, methodName + "units");
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
}
@Test
public void testCreateDuplicateIdFails() {
String methodName = "testCreateDuplocateIdFailsText";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
try {
ourPatientDao.create(p);
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Can not create entity with ID[" + methodName + "], a resource with this ID already exists"));
}
}
@Test
public void testUpdateByUrl() {
String methodName = "testUpdateByUrl";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
ourPatientDao.update(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
p = ourPatientDao.read(id.toVersionless());
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
assertEquals(id.toVersionless(), p.getId().toVersionless());
assertNotEquals(id, p.getId());
assertThat(p.getId().toString(), endsWith("/_history/2"));
}
@Test
public void testCreateNumericIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123");
try {
ourPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Can not create entity with ID[123], this server does not allow clients to assign numeric IDs"));
}
}
@Test
public void testDeleteWithMatchUrl() {
String methodName = "testDeleteWithMatchUrl";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle();
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
ourPatientDao.deleteByUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
ourPatientDao.read(id.toVersionless());
fail();
} catch (ResourceGoneException e) {
// ok
}
try {
ourPatientDao.read(new IdDt("Patient/" + methodName));
fail();
} catch (ResourceNotFoundException e) {
// ok
}
IBundleProvider history = ourPatientDao.history(id, null);
assertEquals(2, history.size());
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1, 1).get(0)));
}
@Test
public void testCreateWithIfNoneExist() {
String methodName = "testCreateWithIfNoneExist";
MethodOutcome results;
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
assertEquals(id.getIdPart(), results.getId().getIdPart());
assertFalse(results.getCreated().booleanValue());
// Now create a second one
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName + "DOESNTEXIST");
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName + "DOESNTEXIST");
assertNotEquals(id.getIdPart(), results.getId().getIdPart());
assertTrue(results.getCreated().booleanValue());
// Now try to create one with the original match URL and it should fail
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
try {
ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
fail();
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("Failed to CREATE"));
}
}
@Test @Test
public void testChoiceParamConcept() { public void testChoiceParamConcept() {
Observation o1 = new Observation(); Observation o1 = new Observation();
@ -350,6 +174,74 @@ public class FhirResourceDaoTest {
} }
} }
@Test
public void testCreateNumericIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123");
try {
ourPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Can not create resource with ID[123], ID must not be supplied"));
}
}
@Test
public void testCreateTextIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateTextIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/ABC");
try {
ourPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Can not create resource with ID[ABC], ID must not be supplied"));
}
}
@Test
public void testCreateWithIfNoneExist() {
String methodName = "testCreateWithIfNoneExist";
MethodOutcome results;
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
assertEquals(id.getIdPart(), results.getId().getIdPart());
assertFalse(results.getCreated().booleanValue());
// Now create a second one
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
results = ourPatientDao.create(p);
assertNotEquals(id.getIdPart(), results.getId().getIdPart());
assertTrue(results.getCreated().booleanValue());
// Now try to create one with the original match URL and it should fail
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
try {
ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
fail();
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("Failed to CREATE"));
}
}
@Test @Test
public void testCreateWithInvalidReferenceFailsGracefully() { public void testCreateWithInvalidReferenceFailsGracefully() {
Patient patient = new Patient(); Patient patient = new Patient();
@ -565,6 +457,67 @@ public class FhirResourceDaoTest {
} }
@Test
public void testDeleteWithMatchUrl() {
String methodName = "testDeleteWithMatchUrl";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle();
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
ourPatientDao.deleteByUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
ourPatientDao.read(id.toVersionless());
fail();
} catch (ResourceGoneException e) {
// ok
}
try {
ourPatientDao.read(new IdDt("Patient/" + methodName));
fail();
} catch (ResourceNotFoundException e) {
// ok
}
IBundleProvider history = ourPatientDao.history(id, null);
assertEquals(2, history.size());
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1, 1).get(0)));
}
@Test
public void testHistoryByForcedId() {
IdDt idv1;
IdDt idv2;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("testHistoryByForcedId");
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedId");
patient.setId("Patient/testHistoryByForcedId");
idv1 = ourPatientDao.update(patient).getId();
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedIdName2");
patient.setId(patient.getId().toUnqualifiedVersionless());
idv2 = ourPatientDao.update(patient).getId();
}
List<Patient> patients = toList(ourPatientDao.history(idv1.toVersionless(), null));
assertTrue(patients.size() == 2);
// Newest first
assertEquals("Patient/testHistoryByForcedId/_history/2", patients.get(0).getId().toUnqualified().getValue());
assertEquals("Patient/testHistoryByForcedId/_history/1", patients.get(1).getId().toUnqualified().getValue());
assertNotEquals(idv1, idv2);
}
@Test @Test
public void testIdParam() { public void testIdParam() {
Patient patient = new Patient(); Patient patient = new Patient();
@ -825,6 +778,29 @@ public class FhirResourceDaoTest {
} }
@Test
public void testReadForcedIdVersionHistory() throws InterruptedException {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
p1.setId("testReadVorcedIdVersionHistory");
IdDt p1id = ourPatientDao.update(p1).getId();
assertEquals("testReadVorcedIdVersionHistory", p1id.getIdPart());
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory02");
p1.setId(p1id);
IdDt p1idv2 = ourPatientDao.update(p1).getId();
assertEquals("testReadVorcedIdVersionHistory", p1idv2.getIdPart());
assertNotEquals(p1id.getValue(), p1idv2.getValue());
Patient v1 = ourPatientDao.read(p1id);
assertEquals(1, v1.getIdentifier().size());
Patient v2 = ourPatientDao.read(p1idv2);
assertEquals(2, v2.getIdentifier().size());
}
@Test @Test
public void testSearchAll() { public void testSearchAll() {
{ {
@ -845,30 +821,6 @@ public class FhirResourceDaoTest {
assertTrue(patients.size() >= 2); assertTrue(patients.size() >= 2);
} }
@Test
public void testHistoryByForcedId() {
IdDt idv1;
IdDt idv2;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("testHistoryByForcedId");
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedId");
patient.setId("Patient/testHistoryByForcedId");
idv1 = ourPatientDao.create(patient).getId();
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedIdName2");
patient.setId(patient.getId().toUnqualifiedVersionless());
idv2 = ourPatientDao.update(patient).getId();
}
List<Patient> patients = toList(ourPatientDao.history(idv1.toVersionless(), null));
assertTrue(patients.size() == 2);
// Newest first
assertEquals("Patient/testHistoryByForcedId/_history/2", patients.get(0).getId().toUnqualified().getValue());
assertEquals("Patient/testHistoryByForcedId/_history/1", patients.get(1).getId().toUnqualified().getValue());
assertNotEquals(idv1, idv2);
}
@Test @Test
public void testSearchByIdParam() { public void testSearchByIdParam() {
IdDt id1; IdDt id1;
@ -968,6 +920,47 @@ public class FhirResourceDaoTest {
} }
} }
@Test
public void testSearchLanguageParam() {
IdDt id1;
{
Patient patient = new Patient();
patient.getLanguage().setValue("en_CA");
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().addFamily("testSearchLanguageParam").addGiven("Joe");
id1 = ourPatientDao.create(patient).getId();
}
IdDt id2;
{
Patient patient = new Patient();
patient.getLanguage().setValue("en_US");
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().addFamily("testSearchLanguageParam").addGiven("John");
id2 = ourPatientDao.create(patient).getId();
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_CA"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(1, patients.size());
assertEquals(id1.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_US"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(1, patients.size());
assertEquals(id2.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_GB"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(0, patients.size());
}
}
@Test @Test
public void testSearchNameParam() { public void testSearchNameParam() {
IdDt id1; IdDt id1;
@ -1091,58 +1084,6 @@ public class FhirResourceDaoTest {
} }
@Test
public void testSearchResourceLinkWithTextLogicalId() {
Patient patient = new Patient();
patient.setId("testSearchResourceLinkWithTextLogicalId01");
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId01");
IdDt patientId01 = ourPatientDao.create(patient).getId();
Patient patient02 = new Patient();
patient02.setId("testSearchResourceLinkWithTextLogicalId02");
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId02");
IdDt patientId02 = ourPatientDao.create(patient02).getId();
Observation obs01 = new Observation();
obs01.setApplies(new DateTimeDt(new Date()));
obs01.setSubject(new ResourceReferenceDt(patientId01));
IdDt obsId01 = ourObservationDao.create(obs01).getId();
Observation obs02 = new Observation();
obs02.setApplies(new DateTimeDt(new Date()));
obs02.setSubject(new ResourceReferenceDt(patientId02));
IdDt obsId02 = ourObservationDao.create(obs02).getId();
// Create another type, that shouldn't be returned
DiagnosticReport dr01 = new DiagnosticReport();
dr01.setSubject(new ResourceReferenceDt(patientId01));
IdDt drId01 = ourDiagnosticReportDao.create(dr01).getId();
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[] { patientId01, patientId02, obsId01, obsId02, drId01 });
List<Observation> result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId01")));
assertEquals(1, result.size());
assertEquals(obsId01.getIdPart(), result.get(0).getId().getIdPart());
try {
ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId99"));
fail();
} catch (ResourceNotFoundException e) {
// good
}
/*
* TODO: it's kind of weird that we throw a 404 for textual IDs that don't exist, but just return an empty list
* for numeric IDs that don't exist
*/
result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("999999999999999")));
assertEquals(0, result.size());
}
@Test @Test
public void testSearchResourceLinkWithChainWithMultipleTypes() { public void testSearchResourceLinkWithChainWithMultipleTypes() {
Patient patient = new Patient(); Patient patient = new Patient();
@ -1181,6 +1122,57 @@ public class FhirResourceDaoTest {
} }
@Test
public void testSearchResourceLinkWithTextLogicalId() {
Patient patient = new Patient();
patient.setId("testSearchResourceLinkWithTextLogicalId01");
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId01");
IdDt patientId01 = ourPatientDao.update(patient).getId();
Patient patient02 = new Patient();
patient02.setId("testSearchResourceLinkWithTextLogicalId02");
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId02");
IdDt patientId02 = ourPatientDao.update(patient02).getId();
Observation obs01 = new Observation();
obs01.setApplies(new DateTimeDt(new Date()));
obs01.setSubject(new ResourceReferenceDt(patientId01));
IdDt obsId01 = ourObservationDao.create(obs01).getId();
Observation obs02 = new Observation();
obs02.setApplies(new DateTimeDt(new Date()));
obs02.setSubject(new ResourceReferenceDt(patientId02));
IdDt obsId02 = ourObservationDao.create(obs02).getId();
// Create another type, that shouldn't be returned
DiagnosticReport dr01 = new DiagnosticReport();
dr01.setSubject(new ResourceReferenceDt(patientId01));
IdDt drId01 = ourDiagnosticReportDao.create(dr01).getId();
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[] { patientId01, patientId02, obsId01, obsId02, drId01 });
List<Observation> result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId01")));
assertEquals(1, result.size());
assertEquals(obsId01.getIdPart(), result.get(0).getId().getIdPart());
try {
ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId99"));
fail();
} catch (ResourceNotFoundException e) {
// good
}
/*
* TODO: it's kind of weird that we throw a 404 for textual IDs that don't exist, but just return an empty list for numeric IDs that don't exist
*/
result = toList(ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("999999999999999")));
assertEquals(0, result.size());
}
@Test @Test
public void testSearchStringParam() { public void testSearchStringParam() {
{ {
@ -1207,47 +1199,6 @@ public class FhirResourceDaoTest {
} }
@Test
public void testSearchLanguageParam() {
IdDt id1;
{
Patient patient = new Patient();
patient.getLanguage().setValue("en_CA");
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().addFamily("testSearchLanguageParam").addGiven("Joe");
id1 = ourPatientDao.create(patient).getId();
}
IdDt id2;
{
Patient patient = new Patient();
patient.getLanguage().setValue("en_US");
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().addFamily("testSearchLanguageParam").addGiven("John");
id2 = ourPatientDao.create(patient).getId();
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_CA"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(1, patients.size());
assertEquals(id1.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_US"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(1, patients.size());
assertEquals(id2.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
}
{
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_GB"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(0, patients.size());
}
}
@Test @Test
public void testSearchStringParamWithNonNormalized() { public void testSearchStringParamWithNonNormalized() {
{ {
@ -1281,7 +1232,8 @@ public class FhirResourceDaoTest {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam001"); patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam001");
patient.addName().addFamily("Tester").addGiven("testSearchTokenParam1"); patient.addName().addFamily("Tester").addGiven("testSearchTokenParam1");
patient.addCommunication().setText("testSearchTokenParamComText").addCoding().setCode("testSearchTokenParamCode").setSystem("testSearchTokenParamSystem").setDisplay("testSearchTokenParamDisplay"); patient.addCommunication().setText("testSearchTokenParamComText").addCoding().setCode("testSearchTokenParamCode").setSystem("testSearchTokenParamSystem")
.setDisplay("testSearchTokenParamDisplay");
ourPatientDao.create(patient); ourPatientDao.create(patient);
patient = new Patient(); patient = new Patient();
@ -1336,6 +1288,41 @@ public class FhirResourceDaoTest {
} }
} }
@Test
public void testSearchValueQuantity() {
String methodName = "testSearchValueQuantity";
QuantityParam param;
Set<Long> found;
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
found = ourObservationDao.searchForIds("value-quantity", param);
int initialSize = found.size();
Observation o = new Observation();
o.getCode().addCoding().setSystem("urn:foo").setCode(methodName + "code");
QuantityDt q = new QuantityDt().setSystem("urn:bar:" + methodName).setCode(methodName + "units").setValue(100);
o.setValue(q);
ourObservationDao.create(o);
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1 + initialSize, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, methodName + "units");
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, null);
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
param = new QuantityParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), "urn:bar:" + methodName, methodName + "units");
found = ourObservationDao.searchForIds("value-quantity", param);
assertEquals(1, found.size());
}
@Test @Test
public void testSearchWithIncludes() { public void testSearchWithIncludes() {
IdDt parentOrgId; IdDt parentOrgId;
@ -1418,23 +1405,6 @@ public class FhirResourceDaoTest {
} }
} }
/**
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
IdDt orgId = ourOrganizationDao.create(org).getId();
Organization returned = ourOrganizationDao.read(orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
/** /**
* Test for #62 * Test for #62
*/ */
@ -1444,7 +1414,7 @@ public class FhirResourceDaoTest {
Organization org = new Organization(); Organization org = new Organization();
org.setId("testSearchWithIncludesThatHaveTextId_id1"); org.setId("testSearchWithIncludesThatHaveTextId_id1");
org.getNameElement().setValue("testSearchWithIncludesThatHaveTextId_O1"); org.getNameElement().setValue("testSearchWithIncludesThatHaveTextId_O1");
IdDt orgId = ourOrganizationDao.create(org).getId(); IdDt orgId = ourOrganizationDao.update(org).getId();
assertThat(orgId.getValue(), endsWith("Organization/testSearchWithIncludesThatHaveTextId_id1/_history/1")); assertThat(orgId.getValue(), endsWith("Organization/testSearchWithIncludesThatHaveTextId_id1/_history/1"));
Patient patient = new Patient(); Patient patient = new Patient();
@ -1491,36 +1461,6 @@ public class FhirResourceDaoTest {
} }
@Test
public void testSortByString() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF1").addGiven("testSortG1");
IdDt id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
// Create out of order
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF3").addGiven("testSortG3");
IdDt id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF2").addGiven("testSortG2");
IdDt id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
IdDt id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
SearchParameterMap pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString"));
pm.setSort(new SortSpec(Patient.SP_FAMILY));
List<IdDt> actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size());
assertThat(actual, contains(id1, id2, id3, id4));
}
@Test @Test
public void testSortByDate() { public void testSortByDate() {
Patient p = new Patient(); Patient p = new Patient();
@ -1572,6 +1512,104 @@ public class FhirResourceDaoTest {
} }
@Test
public void testSortById() {
String methodName = "testSortBTyId";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.setId(methodName);
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt idMethodName = ourPatientDao.update(p).getId().toUnqualifiedVersionless();
assertEquals(methodName, idMethodName.getIdPart());
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
SearchParameterMap pm;
List<IdDt> actual;
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID).setOrder(SortOrderEnum.ASC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID).setOrder(SortOrderEnum.DESC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(id4, id3, id2, id1, idMethodName));
}
@Test
public void testSortByString() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF1").addGiven("testSortG1");
IdDt id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
// Create out of order
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF3").addGiven("testSortG3");
IdDt id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
p.addName().addFamily("testSortF2").addGiven("testSortG2");
IdDt id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString");
IdDt id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
SearchParameterMap pm;
List<IdDt> actual;
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString"));
pm.setSort(new SortSpec(Patient.SP_FAMILY));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size());
assertThat(actual, contains(id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString"));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.ASC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size());
assertThat(actual, contains(id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString"));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.DESC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size());
assertThat(actual, contains(id3, id2, id1, id4));
}
@Test @Test
public void testStoreUnversionedResources() { public void testStoreUnversionedResources() {
Organization o1 = new Organization(); Organization o1 = new Organization();
@ -1590,6 +1628,23 @@ public class FhirResourceDaoTest {
assertEquals(o1id.toUnqualifiedVersionless(), p1.getManagingOrganization().getReference().toUnqualifiedVersionless()); assertEquals(o1id.toUnqualifiedVersionless(), p1.getManagingOrganization().getReference().toUnqualifiedVersionless());
} }
/**
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
IdDt orgId = ourOrganizationDao.create(org).getId();
Organization returned = ourOrganizationDao.read(orgId);
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
ourLog.info(val);
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
}
@Test @Test
public void testStringParamWhichIsTooLong() { public void testStringParamWhichIsTooLong() {
@ -1773,6 +1828,60 @@ public class FhirResourceDaoTest {
} }
@Test
public void testUpdateByUrl() {
String methodName = "testUpdateByUrl";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IdDt id = ourPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
ourPatientDao.update(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
p = ourPatientDao.read(id.toVersionless());
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
assertEquals(id.toVersionless(), p.getId().toVersionless());
assertNotEquals(id, p.getId());
assertThat(p.getId().toString(), endsWith("/_history/2"));
}
@Test
public void testUpdateCreatesTextualIdIfItDoesntAlreadyExist() {
Patient p = new Patient();
String methodName = "testUpdateCreatesTextualIdIfItDoesntAlreadyExist";
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.update(p).getId();
assertEquals("Patient/" + methodName, id.toUnqualifiedVersionless().getValue());
p = ourPatientDao.read(id);
assertEquals(methodName, p.getIdentifierFirstRep().getValue());
}
@Test
public void testUpdateFailsForUnknownIdWithNumberThenText() {
String methodName = "testUpdateFailsForUnknownIdWithNumberThenText";
Patient p = new Patient();
p.setId("0" + methodName);
p.addName().addFamily(methodName);
try {
ourPatientDao.update(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server"));
}
}
@Test @Test
public void testUpdateMaintainsSearchParams() throws InterruptedException { public void testUpdateMaintainsSearchParams() throws InterruptedException {
Patient p1 = new Patient(); Patient p1 = new Patient();
@ -1837,58 +1946,17 @@ public class FhirResourceDaoTest {
} }
@Test @Test
public void testUpdateRejectsIdWhichPointsToForcedId() throws InterruptedException { public void testUpdateUnknownNumericIdFails() {
Patient p1 = new Patient(); Patient p = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId01"); p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p1.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId01"); p.addName().addFamily("Hello");
p1.setId("ABABA"); p.setId("Patient/9999999999999999");
IdDt p1id = ourPatientDao.create(p1).getId();
assertEquals("ABABA", p1id.getIdPart());
Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId02");
p2.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId02");
IdDt p2id = ourPatientDao.create(p2).getId();
long p1longId = p2id.getIdPartAsLong() - 1;
try { try {
ourPatientDao.read(new IdDt("Patient/" + p1longId)); ourPatientDao.update(p);
fail(); fail();
} catch (ResourceNotFoundException e) { } catch (InvalidRequestException e) {
// good assertThat(e.getMessage(), containsString("Can not create resource with ID[9999999999999999], no resource with this ID exists and clients may only"));
} }
try {
p1.setId(new IdDt("Patient/" + p1longId));
ourPatientDao.update(p1);
fail();
} catch (ResourceNotFoundException e) {
// good
}
}
@Test
public void testReadForcedIdVersionHistory() throws InterruptedException {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
p1.setId("testReadVorcedIdVersionHistory");
IdDt p1id = ourPatientDao.create(p1).getId();
assertEquals("testReadVorcedIdVersionHistory", p1id.getIdPart());
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory02");
p1.setId(p1id);
IdDt p1idv2 = ourPatientDao.update(p1).getId();
assertEquals("testReadVorcedIdVersionHistory", p1idv2.getIdPart());
assertNotEquals(p1id.getValue(), p1idv2.getValue());
Patient v1 = ourPatientDao.read(p1id);
assertEquals(1, v1.getIdentifier().size());
Patient v2 = ourPatientDao.read(p1idv2);
assertEquals(2, v2.getIdentifier().size());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -49,7 +49,7 @@ public class FhirSystemDaoDstu2Test {
Patient p = new Patient(); Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName); p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName); p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId(); IdDt id = ourPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id); ourLog.info("Created patient, got it: {}", id);
p = new Patient(); p = new Patient();
@ -91,7 +91,7 @@ public class FhirSystemDaoDstu2Test {
Patient p = new Patient(); Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName); p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName); p.setId("Patient/" + methodName);
IdDt idv1 = ourPatientDao.create(p).getId(); IdDt idv1 = ourPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1); ourLog.info("Created patient, got id: {}", idv1);
p = new Patient(); p = new Patient();
@ -301,7 +301,7 @@ public class FhirSystemDaoDstu2Test {
Patient p2 = new Patient(); Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue(methodName); p2.addIdentifier().setSystem("urn:system").setValue(methodName);
p2.setId("Patient/" + methodName); p2.setId("Patient/" + methodName);
IdDt id2 = ourPatientDao.create(p2).getId(); IdDt id2 = ourPatientDao.update(p2).getId();
ourLog.info("Created patient, got it: {}", id2); ourLog.info("Created patient, got it: {}", id2);
Bundle request = new Bundle(); Bundle request = new Bundle();
@ -356,7 +356,7 @@ public class FhirSystemDaoDstu2Test {
Patient p = new Patient(); Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName); p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName); p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId(); IdDt id = ourPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id); ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle(); Bundle request = new Bundle();
@ -516,7 +516,7 @@ public class FhirSystemDaoDstu2Test {
Patient p = new Patient(); Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName); p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName); p.setId("Patient/" + methodName);
IdDt id = ourPatientDao.create(p).getId(); IdDt id = ourPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id); ourLog.info("Created patient, got it: {}", id);
p = new Patient(); p = new Patient();

View File

@ -415,36 +415,6 @@ public class ResourceProviderDstu2Test {
} }
} }
@Test
public void testCreateWithClientSuppliedId() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system:rpdstu2", "testCreateWithId01");
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testCreateWithId01");
IdDt p1Id = ourClient.create().resource(p1).withId("testCreateWithIdRpDstu2").execute().getId();
assertThat(p1Id.getValue(), containsString("Patient/testCreateWithIdRpDstu2/_history"));
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system:rpdstu2", "testCreateWithId01")).encodedJson().prettyPrint().execute();
assertEquals(1, actual.size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
/*
* ensure that trying to create the same ID again fails appropriately
*/
try {
ourClient.create().resource(p1).withId("testCreateWithIdRpDstu2").execute().getId();
fail();
} catch (UnprocessableEntityException e) {
// good
}
Bundle history = ourClient.history(null, (String) null, null, null);
assertEquals("Expected[" + p1Id.getIdPart() + "] but was " + history.getEntries().get(0).getResource().getId(), p1Id.getIdPart(), history.getEntries().get(0).getResource().getId().getIdPart());
assertNotNull(history.getEntries().get(0).getResource());
}
@Test @Test
public void testDeepChaining() { public void testDeepChaining() {
delete("Location", Location.SP_NAME, "testDeepChainingL1"); delete("Location", Location.SP_NAME, "testDeepChainingL1");