diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/model/dstu/composite/ResourceReferenceDtTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/model/dstu/composite/ResourceReferenceDtTest.java
new file mode 100644
index 00000000000..be7876c3614
--- /dev/null
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/model/dstu/composite/ResourceReferenceDtTest.java
@@ -0,0 +1,100 @@
+package ca.uhn.fhir.model.dstu.composite;
+
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.dstu.resource.Observation;
+import ca.uhn.fhir.model.dstu.resource.Organization;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+
+public class ResourceReferenceDtTest {
+
+ private static FhirContext ourCtx;
+
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceReferenceDtTest.class);
+
+ @Test
+ public void testParseValueAbsolute() {
+ Patient patient = new Patient();
+ ResourceReferenceDt rr = new ResourceReferenceDt();
+ rr.setReference("http://foo/fhir/Organization/123");
+ patient.setManagingOrganization(rr);
+
+ Patient actual = parseAndEncode(patient);
+ rr = actual.getManagingOrganization();
+ assertEquals(Organization.class, rr.getResourceType());
+ assertEquals("123", rr.getResourceId());
+
+ }
+
+ @Test
+ public void testParseValueMissingType1() {
+ Patient patient = new Patient();
+ ResourceReferenceDt rr = new ResourceReferenceDt();
+ rr.setReference("/123");
+ patient.setManagingOrganization(rr);
+
+ Patient actual = parseAndEncode(patient);
+ rr = actual.getManagingOrganization();
+ assertEquals(null, rr.getResourceType());
+ assertEquals("123", rr.getResourceId());
+
+ }
+
+ @Test
+ public void testParseValueMissingType2() {
+ Patient patient = new Patient();
+ ResourceReferenceDt rr = new ResourceReferenceDt();
+ rr.setReference("123");
+ patient.setManagingOrganization(rr);
+
+ Patient actual = parseAndEncode(patient);
+ rr = actual.getManagingOrganization();
+ assertEquals(null, rr.getResourceType());
+ assertEquals("123", rr.getResourceId());
+
+ }
+
+ @Test
+ public void testParseValueRelative1() {
+ Patient patient = new Patient();
+ ResourceReferenceDt rr = new ResourceReferenceDt();
+ rr.setReference("Organization/123");
+ patient.setManagingOrganization(rr);
+
+ Patient actual = parseAndEncode(patient);
+ rr = actual.getManagingOrganization();
+ assertEquals(Organization.class, rr.getResourceType());
+ assertEquals("123", rr.getResourceId());
+
+ }
+
+ @Test
+ public void testParseValueRelative2() {
+ Patient patient = new Patient();
+ ResourceReferenceDt rr = new ResourceReferenceDt();
+ rr.setReference("/Organization/123");
+ patient.setManagingOrganization(rr);
+
+ Patient actual = parseAndEncode(patient);
+ rr = actual.getManagingOrganization();
+ assertEquals(Organization.class, rr.getResourceType());
+ assertEquals("123", rr.getResourceId());
+
+ }
+
+ private Patient parseAndEncode(Patient patient) {
+ String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
+ ourLog.info("\n" + encoded);
+ return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ ourCtx = new FhirContext();
+ }
+
+}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ReferenceClientTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ReferenceClientTest.java
new file mode 100644
index 00000000000..9450bc3e0fd
--- /dev/null
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ReferenceClientTest.java
@@ -0,0 +1,129 @@
+package ca.uhn.fhir.rest.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.apache.commons.io.input.ReaderInputStream;
+import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.message.BasicStatusLine;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.Bundle;
+import ca.uhn.fhir.model.dstu.resource.Conformance;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.rest.annotation.RequiredParam;
+import ca.uhn.fhir.rest.annotation.Search;
+import ca.uhn.fhir.rest.client.api.IBasicClient;
+import ca.uhn.fhir.rest.param.ReferenceParam;
+import ca.uhn.fhir.rest.param.StringParam;
+import ca.uhn.fhir.rest.server.Constants;
+
+public class ReferenceClientTest {
+
+ private FhirContext ctx;
+ private HttpClient httpClient;
+ private HttpResponse httpResponse;
+
+ // atom-document-large.xml
+
+ @Before
+ public void before() {
+ ctx = new FhirContext(Patient.class, Conformance.class);
+
+ httpClient = mock(HttpClient.class, new ReturnsDeepStubs());
+ ctx.getRestfulClientFactory().setHttpClient(httpClient);
+
+ httpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
+ }
+
+ @Test
+ public void testWithParam() throws Exception {
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
+ when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
+ when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
+
+ IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
+ client.search(new ReferenceParam("123"));
+
+ assertEquals(HttpGet.class, capt.getValue().getClass());
+ HttpGet get = (HttpGet) capt.getValue();
+ assertEquals("http://foo/Patient?provider=123", get.getURI().toString());
+ }
+
+ @Test
+ public void testWithParamAndChain() throws Exception {
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
+ when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
+ when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
+
+ IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
+ client.search(new ReferenceParam("chain", "123"));
+
+ assertEquals(HttpGet.class, capt.getValue().getClass());
+ HttpGet get = (HttpGet) capt.getValue();
+ assertEquals("http://foo/Patient?provider.chain=123", get.getURI().toString());
+ }
+
+ @Test
+ public void testWithParamAndTypeAndChain() throws Exception {
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
+ when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
+ when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
+
+ IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
+ client.search(new ReferenceParam("Organization", "chain", "123"));
+
+ assertEquals(HttpGet.class, capt.getValue().getClass());
+ HttpGet get = (HttpGet) capt.getValue();
+ assertEquals("http://foo/Patient?provider%3AOrganization.chain=123", get.getURI().toString());
+ }
+
+ @Test
+ public void testWithParamAndType() throws Exception {
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
+ when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
+ when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
+
+ IClient client = ctx.newRestfulClient(IClient.class, "http://foo");
+ client.search(new ReferenceParam("Organization", null, "123"));
+
+ assertEquals(HttpGet.class, capt.getValue().getClass());
+ HttpGet get = (HttpGet) capt.getValue();
+ assertEquals("http://foo/Patient?provider%3AOrganization=123", get.getURI().toString());
+ }
+
+ private String createBundle() {
+ return ctx.newXmlParser().encodeBundleToString(new Bundle());
+ }
+
+
+ private interface IClient extends IBasicClient {
+
+ @Search(type=Patient.class)
+ public List search(@RequiredParam(name=Patient.SP_PROVIDER) ReferenceParam theString);
+
+ }
+
+}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ReferenceParameterTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ReferenceParameterTest.java
new file mode 100644
index 00000000000..ae3724d1234
--- /dev/null
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ReferenceParameterTest.java
@@ -0,0 +1,165 @@
+package ca.uhn.fhir.rest.server;
+
+import static org.apache.commons.lang3.StringUtils.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.BundleEntry;
+import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.rest.annotation.RequiredParam;
+import ca.uhn.fhir.rest.annotation.Search;
+import ca.uhn.fhir.rest.param.ReferenceParam;
+import ca.uhn.fhir.testutil.RandomServerPortProvider;
+
+/**
+ * Created by dsotnikov on 2/25/2014.
+ */
+public class ReferenceParameterTest {
+
+ private static CloseableHttpClient ourClient;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReferenceParameterTest.class);
+ private static int ourPort;
+ private static Server ourServer;
+ private static FhirContext ourCtx;
+
+
+
+
+ @Test
+ public void testSearchWithValue() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+"=123");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ List entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
+ assertEquals(1, entries.size());
+ Patient p = (Patient) entries.get(0).getResource();
+ assertEquals("0123",p.getName().get(0).getFamilyFirstRep().getValue());
+ assertEquals("1",p.getName().get(1).getFamilyFirstRep().getValue());
+ assertEquals("2",p.getName().get(2).getFamilyFirstRep().getValue());
+ }
+ }
+
+ @Test
+ public void testSearchWithValueAndType() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+":Organization=123");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ List entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
+ assertEquals(1, entries.size());
+ Patient p = (Patient) entries.get(0).getResource();
+ assertEquals("0123",p.getName().get(0).getFamilyFirstRep().getValue());
+ assertEquals("1Organization",p.getName().get(1).getFamilyFirstRep().getValue());
+ assertEquals("2",p.getName().get(2).getFamilyFirstRep().getValue());
+ }
+ }
+ @Test
+ public void testSearchWithValueAndTypeAndChain() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+":Organization.name=123");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ List entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
+ assertEquals(1, entries.size());
+ Patient p = (Patient) entries.get(0).getResource();
+ assertEquals("0123",p.getName().get(0).getFamilyFirstRep().getValue());
+ assertEquals("1Organization",p.getName().get(1).getFamilyFirstRep().getValue());
+ assertEquals("2name",p.getName().get(2).getFamilyFirstRep().getValue());
+ }
+ }
+
+ @Test
+ public void testSearchWithValueAndChain() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+".name=123");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ List entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
+ assertEquals(1, entries.size());
+ Patient p = (Patient) entries.get(0).getResource();
+ assertEquals("0123",p.getName().get(0).getFamilyFirstRep().getValue());
+ assertEquals("1",p.getName().get(1).getFamilyFirstRep().getValue());
+ assertEquals("2name",p.getName().get(2).getFamilyFirstRep().getValue());
+ }
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ ourServer.stop();
+ }
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ ourPort = RandomServerPortProvider.findFreePort();
+ ourServer = new Server(ourPort);
+
+ DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
+
+ ServletHandler proxyHandler = new ServletHandler();
+ RestfulServer servlet = new RestfulServer();
+ servlet.setResourceProviders(patientProvider);
+ ServletHolder servletHolder = new ServletHolder(servlet);
+ proxyHandler.addServletWithMapping(servletHolder, "/*");
+ ourServer.setHandler(proxyHandler);
+ ourServer.start();
+
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
+ HttpClientBuilder builder = HttpClientBuilder.create();
+ builder.setConnectionManager(connectionManager);
+ ourClient = builder.build();
+
+ ourCtx = servlet.getFhirContext();
+ }
+
+ /**
+ * Created by dsotnikov on 2/25/2014.
+ */
+ public static class DummyPatientResourceProvider implements IResourceProvider {
+
+ @Search
+ public List findPatient(@RequiredParam(name = Patient.SP_PROVIDER) ReferenceParam theParam) {
+ ArrayList retVal = new ArrayList();
+
+ Patient p = new Patient();
+ p.addName().addFamily("0"+theParam.getValueAsQueryToken());
+ p.addName().addFamily("1"+defaultString(theParam.getResourceType()));
+ p.addName().addFamily("2"+defaultString(theParam.getChain()));
+ retVal.add(p);
+
+ return retVal;
+ }
+
+
+
+
+ @Override
+ public Class extends IResource> getResourceType() {
+ return Patient.class;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
index db918872d6c..9d7a7c31592 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResourceMethodTest.java
@@ -96,7 +96,9 @@ public class ResourceMethodTest {
inputParams.add("lastName");
inputParams.add("mrn");
- assertEquals(true, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestType.GET, inputParams))); // True
+ Request params = Request.withResourceAndParams("Patient", RequestType.GET, inputParams);
+ boolean actual = rm.incomingServerRequestMatchesMethod(params);
+ assertTrue( actual); // True
}
@Test
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/DocumentationTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java
similarity index 56%
rename from hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/DocumentationTest.java
rename to hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java
index 877a1c41c9a..8f45124b7d8 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/DocumentationTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java
@@ -13,6 +13,8 @@ import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.model.primitive.StringDt;
+import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
@@ -20,9 +22,9 @@ import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.param.SearchParameter;
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
-public class DocumentationTest {
+public class ServerConformanceProviderTest {
- private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DocumentationTest.class);
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerConformanceProviderTest.class);
@Test
public void testSearchParameterDocumentation() throws Exception {
@@ -55,6 +57,39 @@ public class DocumentationTest {
assertThat(conf, containsString(""));
}
+
+ @Test
+ public void testMultiOptionalDocumentation() throws Exception {
+
+ RestfulServer rs = new RestfulServer();
+ rs.setProviders(new MultiOptionalProvider());
+
+ ServerConformanceProvider sc = new ServerConformanceProvider(rs);
+ rs.setServerConformanceProvider(sc);
+
+ rs.init(null);
+
+ boolean found=false;
+ Collection resourceBindings = rs.getResourceBindings();
+ for (ResourceBinding resourceBinding : resourceBindings) {
+ if (resourceBinding.getResourceName().equals("Patient")) {
+ List> methodBindings = resourceBinding.getMethodBindings();
+ SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
+ SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
+ assertEquals("The patient's identifier", param.getDescription());
+ found=true;
+ }
+ }
+ assertTrue(found);
+ Conformance conformance = sc.getServerConformance();
+ String conf = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
+ ourLog.info(conf);
+
+ assertThat(conf, containsString(""));
+ assertThat(conf, containsString(""));
+ }
+
+
/**
* Created by dsotnikov on 2/25/2014.
*/
@@ -69,5 +104,23 @@ public class DocumentationTest {
}
}
+
+
+ /**
+ * Created by dsotnikov on 2/25/2014.
+ */
+ @SuppressWarnings("unused")
+ public static class MultiOptionalProvider {
+
+ @Search(type = Patient.class)
+ public Patient findPatient(
+ @Description(shortDefinition = "The patient's identifier")
+ @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier,
+ @Description(shortDefinition = "The patient's name")
+ @OptionalParam(name=Patient.SP_NAME) StringDt theName) {
+ return null;
+ }
+
+ }
}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/SortTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/SortTest.java
new file mode 100644
index 00000000000..73194d27d50
--- /dev/null
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/SortTest.java
@@ -0,0 +1,177 @@
+package ca.uhn.fhir.rest.server;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.Bundle;
+import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.model.primitive.StringDt;
+import ca.uhn.fhir.rest.annotation.RequiredParam;
+import ca.uhn.fhir.rest.annotation.Search;
+import ca.uhn.fhir.rest.annotation.Sort;
+import ca.uhn.fhir.rest.api.SortSpec;
+import ca.uhn.fhir.testutil.RandomServerPortProvider;
+
+/**
+ * Created by dsotnikov on 2/25/2014.
+ */
+public class SortTest {
+
+ private static CloseableHttpClient ourClient;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SortTest.class);
+ private static int ourPort;
+ private static Server ourServer;
+
+ @Test
+ public void testNoSort() throws Exception {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
+ assertEquals(1, bundle.size());
+
+ Patient p = bundle.getResources(Patient.class).get(0);
+ assertEquals(1, p.getName().size());
+ assertEquals("Hello", p.getNameFirstRep().getFamilyFirstRep().getValue());
+ }
+
+ @Test
+ public void testSingleSort() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort=given");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
+ assertEquals(1, bundle.size());
+
+ Patient p = bundle.getResources(Patient.class).get(0);
+ assertEquals(2, p.getName().size());
+ assertEquals("Hello", p.getNameFirstRep().getFamilyFirstRep().getValue());
+ assertEquals("given|null", p.getName().get(1).getFamilyFirstRep().getValue());
+ }
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort:asc=given");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
+ assertEquals(1, bundle.size());
+
+ Patient p = bundle.getResources(Patient.class).get(0);
+ assertEquals(2, p.getName().size());
+ assertEquals("Hello", p.getNameFirstRep().getFamilyFirstRep().getValue());
+ assertEquals("given|ASC", p.getName().get(1).getFamilyFirstRep().getValue());
+ }
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort:desc=given");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
+ assertEquals(1, bundle.size());
+
+ Patient p = bundle.getResources(Patient.class).get(0);
+ assertEquals(2, p.getName().size());
+ assertEquals("Hello", p.getNameFirstRep().getFamilyFirstRep().getValue());
+ assertEquals("given|DESC", p.getName().get(1).getFamilyFirstRep().getValue());
+ }
+
+ }
+
+ @Test
+ public void testSortChain() throws Exception {
+ {
+ HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort=given&_sort=family&_sort=name");
+ HttpResponse status = ourClient.execute(httpGet);
+ String responseContent = IOUtils.toString(status.getEntity().getContent());
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
+ assertEquals(1, bundle.size());
+
+ Patient p = bundle.getResources(Patient.class).get(0);
+ assertEquals(4, p.getName().size());
+ assertEquals("Hello", p.getNameFirstRep().getFamilyFirstRep().getValue());
+ assertEquals("given|null", p.getName().get(1).getFamilyFirstRep().getValue());
+ assertEquals("family|null", p.getName().get(2).getFamilyFirstRep().getValue());
+ assertEquals("name|null", p.getName().get(3).getFamilyFirstRep().getValue());
+ }
+
+
+ }
+ @AfterClass
+ public static void afterClass() throws Exception {
+ ourServer.stop();
+ }
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ ourPort = RandomServerPortProvider.findFreePort();
+ ourServer = new Server(ourPort);
+
+ DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
+
+ ServletHandler proxyHandler = new ServletHandler();
+ RestfulServer servlet = new RestfulServer();
+ servlet.setResourceProviders(patientProvider);
+ ServletHolder servletHolder = new ServletHolder(servlet);
+ proxyHandler.addServletWithMapping(servletHolder, "/*");
+ ourServer.setHandler(proxyHandler);
+ ourServer.start();
+
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
+ HttpClientBuilder builder = HttpClientBuilder.create();
+ builder.setConnectionManager(connectionManager);
+ ourClient = builder.build();
+
+ }
+
+ /**
+ * Created by dsotnikov on 2/25/2014.
+ */
+ public static class DummyPatientResourceProvider implements IResourceProvider {
+
+ @Search
+ public List findPatient(@RequiredParam(name = Patient.SP_NAME) StringDt theName, @Sort SortSpec theSort) {
+ ArrayList retVal = new ArrayList();
+
+ Patient p = new Patient();
+ p.addName().addFamily().setValue(theName.getValue());
+ SortSpec sort = theSort;
+ while (sort != null) {
+ p.addName().addFamily().setValue(sort.getFieldName() + "|" + sort.getOrder());
+ sort = sort.getChain();
+ }
+
+ retVal.add(p);
+
+ return retVal;
+ }
+
+ @Override
+ public Class extends IResource> getResourceType() {
+ return Patient.class;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-base/.classpath b/hapi-fhir-jpaserver-base/.classpath
index 3e436a199d8..15f6337d7f2 100644
--- a/hapi-fhir-jpaserver-base/.classpath
+++ b/hapi-fhir-jpaserver-base/.classpath
@@ -1,151 +1,152 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-base/.gitignore b/hapi-fhir-jpaserver-base/.gitignore
index 2f7896d1d13..548aaf5e303 100644
--- a/hapi-fhir-jpaserver-base/.gitignore
+++ b/hapi-fhir-jpaserver-base/.gitignore
@@ -1 +1,2 @@
target/
+/bin
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index cef4a355993..0801ca5194f 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -175,6 +175,59 @@
true
+
+
+ de.juplo
+ hibernate4-maven-plugin
+ 1.0.1
+
+ true
+ SCRIPT
+ false
+
+
+
+ o10g
+
+ export
+
+
+ org.hibernate.dialect.Oracle10gDialect
+ ${project.build.directory}/schema_oracle_10g.sql
+
+
+
+ derby
+
+ export
+
+
+ org.hibernate.dialect.DerbyTenSevenDialect
+ ${project.build.directory}/schema_derby.sql
+
+
+
+ hsql
+
+ export
+
+
+ org.hibernate.dialect.HSQLDialect
+ ${project.build.directory}/schema_hsql.sql
+
+
+
+ mysql5
+
+ export
+
+
+ org.hibernate.dialect.MySQL5Dialect
+ ${project.build.directory}/schema_mysql_5.sql
+
+
+
+
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java
index c8f55acfaf0..8a3c526d72d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java
@@ -56,8 +56,10 @@ import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
+import ca.uhn.fhir.model.dstu.composite.AddressDt;
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
+import ca.uhn.fhir.model.dstu.composite.ContactDt;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
@@ -96,6 +98,312 @@ public class FhirResourceDao
private Class myTableType;
+ @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
+ @Override
+ public MethodOutcome create(T theResource) {
+
+ final X entity = toEntity(theResource);
+
+ entity.setPublished(new Date());
+ entity.setUpdated(entity.getPublished());
+
+ final List stringParams = extractSearchParamStrings(entity, theResource);
+ final List tokenParams = extractSearchParamTokens(entity, theResource);
+ final List numberParams = extractSearchParamNumber(entity, theResource);
+ final List dateParams = extractSearchParamDates(entity, theResource);
+ final List links = extractResourceLinks(entity, theResource);
+
+ ourLog.info("Saving links: {}", links);
+
+ TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager);
+ template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
+ template.setReadOnly(false);
+ template.execute(new TransactionCallback() {
+ @Override
+ public X doInTransaction(TransactionStatus theStatus) {
+ myEntityManager.persist(entity);
+ for (ResourceIndexedSearchParamString next : stringParams) {
+ myEntityManager.persist(next);
+ }
+ for (ResourceIndexedSearchParamToken next : tokenParams) {
+ myEntityManager.persist(next);
+ }
+ for (ResourceIndexedSearchParamNumber next : numberParams) {
+ myEntityManager.persist(next);
+ }
+ for (ResourceIndexedSearchParamDate next : dateParams) {
+ myEntityManager.persist(next);
+ }
+ for (ResourceLink next : links) {
+ myEntityManager.persist(next);
+ }
+ return entity;
+ }
+ });
+
+ MethodOutcome outcome = toMethodOutcome(entity);
+ return outcome;
+ }
+
+ public Class getResourceType() {
+ return myResourceType;
+ }
+
+ @Override
+ public Class getTableType() {
+ return myTableType;
+ }
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ @Override
+ public List history(IdDt theId) {
+ ArrayList retVal = new ArrayList();
+
+ String resourceType = myCtx.getResourceDefinition(myResourceType).getName();
+ TypedQuery q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class);
+ q.setParameter("PID", theId.asLong());
+ q.setParameter("RESTYPE", resourceType);
+
+ // TypedQuery query =
+ // myEntityManager.createQuery(criteriaQuery);
+ List results = q.getResultList();
+ for (ResourceHistoryTable next : results) {
+ retVal.add(toResource(next));
+ }
+
+ try {
+ retVal.add(read(theId));
+ } catch (ResourceNotFoundException e) {
+ // ignore
+ }
+
+ if (retVal.isEmpty()) {
+ throw new ResourceNotFoundException(theId);
+ }
+
+ return retVal;
+ }
+
+ @PostConstruct
+ public void postConstruct() throws Exception {
+ myResourceType = myTableType.newInstance().getResourceType();
+ myCtx = new FhirContext(myResourceType);
+ myResourceName = myCtx.getResourceDefinition(myResourceType).getName();
+ }
+
+ @Transactional(propagation = Propagation.REQUIRED)
+ @Override
+ public T read(IdDt theId) {
+ X entity = readEntity(theId);
+
+ T retVal = toResource(entity);
+ return retVal;
+ }
+
+ @Override
+ public List search(Map theParams) {
+ SearchParameterMap map = new SearchParameterMap();
+ for (Entry nextEntry : theParams.entrySet()) {
+ map.put(nextEntry.getKey(), new ArrayList>());
+ map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue()));
+ }
+ return search(map);
+ }
+
+ @Override
+ public List search(SearchParameterMap theParams) {
+
+ Set pids;
+ if (theParams.isEmpty()) {
+ pids = null;
+ } else {
+ pids = searchForIdsWithAndOr(theParams);
+ if (pids.isEmpty()) {
+ return new ArrayList<>();
+ }
+ }
+
+ // Execute the query and make sure we return distinct results
+ {
+ CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
+ CriteriaQuery cq = builder.createQuery(myTableType);
+ Root from = cq.from(myTableType);
+ if (!theParams.isEmpty()) {
+ cq.where(from.get("myId").in(pids));
+ }
+ TypedQuery q = myEntityManager.createQuery(cq);
+
+ List retVal = new ArrayList<>();
+ for (X next : q.getResultList()) {
+ T resource = toResource(next);
+ retVal.add(resource);
+ }
+ return retVal;
+ }
+ }
+
+ @Override
+ public List search(String theParameterName, IQueryParameterType theValue) {
+ return search(Collections.singletonMap(theParameterName, theValue));
+ }
+
+ @Override
+ public Set searchForIds(Map theParams) {
+ Map>> map = new HashMap>>();
+ for (Entry nextEntry : theParams.entrySet()) {
+ map.put(nextEntry.getKey(), new ArrayList>());
+ map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue()));
+ }
+ return searchForIdsWithAndOr(map);
+ }
+
+ @Override
+ public Set searchForIds(String theParameterName, IQueryParameterType theValue) {
+ return searchForIds(Collections.singletonMap(theParameterName, theValue));
+ }
+
+ @Override
+ public Set searchForIdsWithAndOr(Map>> theParams) {
+ Map>> params = theParams;
+ if (params == null) {
+ params = Collections.emptyMap();
+ }
+
+ RuntimeResourceDefinition resourceDef = myCtx.getResourceDefinition(myResourceType);
+
+ Set pids = new HashSet();
+
+ for (Entry>> nextParamEntry : params.entrySet()) {
+ String nextParamName = nextParamEntry.getKey();
+ RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName);
+ if (nextParamDef != null) {
+ if (nextParamDef.getParamType() == SearchParamTypeEnum.TOKEN) {
+ for (List nextAnd : nextParamEntry.getValue()) {
+ pids = addPredicateToken(pids, nextAnd);
+ if (pids.isEmpty()) {
+ return new HashSet();
+ }
+ }
+ } else if (nextParamDef.getParamType() == SearchParamTypeEnum.STRING) {
+ for (List nextAnd : nextParamEntry.getValue()) {
+ pids = addPredicateString(pids, nextAnd);
+ if (pids.isEmpty()) {
+ return new HashSet();
+ }
+ }
+ } else if (nextParamDef.getParamType() == SearchParamTypeEnum.QUANTITY) {
+ for (List nextAnd : nextParamEntry.getValue()) {
+ pids = addPredicateQuantity(pids, nextAnd);
+ if (pids.isEmpty()) {
+ return new HashSet();
+ }
+ }
+ } else if (nextParamDef.getParamType() == SearchParamTypeEnum.DATE) {
+ for (List nextAnd : nextParamEntry.getValue()) {
+ pids = addPredicateDate(pids, nextAnd);
+ if (pids.isEmpty()) {
+ return new HashSet();
+ }
+ }
+ } else if (nextParamDef.getParamType() == SearchParamTypeEnum.REFERENCE) {
+ for (List nextAnd : nextParamEntry.getValue()) {
+ pids = addPredicateReference(nextParamName, pids, nextAnd);
+ if (pids.isEmpty()) {
+ return new HashSet();
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Don't know how to handle parameter of type: " + nextParamDef.getParamType());
+ }
+ }
+ }
+
+ return pids;
+ }
+
+ @Required
+ public void setTableType(Class theTableType) {
+ myTableType = theTableType;
+ }
+
+ @Transactional(propagation = Propagation.SUPPORTS)
+ @Override
+ public MethodOutcome update(final T theResource, final IdDt theId) {
+
+ TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager);
+ X savedEntity = template.execute(new TransactionCallback() {
+ @Override
+ public X doInTransaction(TransactionStatus theStatus) {
+
+ final X entity = readEntity(theId);
+ entity.setUpdated(entity.getPublished());
+
+ final ResourceHistoryTable historyEntry = entity.toHistory(myCtx);
+
+ final List stringParams = extractSearchParamStrings(entity, theResource);
+ final List tokenParams = extractSearchParamTokens(entity, theResource);
+ final List numberParams = extractSearchParamNumber(entity, theResource);
+ final List dateParams = extractSearchParamDates(entity, theResource);
+ final List links = extractResourceLinks(entity, theResource);
+
+ populateResourceIntoEntity(theResource, entity);
+ myEntityManager.persist(historyEntry);
+
+ entity.setUpdated(new Date());
+ myEntityManager.persist(entity);
+
+ if (entity.isParamsStringPopulated()) {
+ for (ResourceIndexedSearchParamString next : entity.getParamsString()) {
+ myEntityManager.remove(next);
+ }
+ }
+ for (ResourceIndexedSearchParamString next : stringParams) {
+ myEntityManager.persist(next);
+ }
+
+ if (entity.isParamsTokenPopulated()) {
+ for (ResourceIndexedSearchParamToken next : entity.getParamsToken()) {
+ myEntityManager.remove(next);
+ }
+ }
+ for (ResourceIndexedSearchParamToken next : tokenParams) {
+ myEntityManager.persist(next);
+ }
+
+ if (entity.isParamsNumberPopulated()) {
+ for (ResourceIndexedSearchParamNumber next : entity.getParamsNumber()) {
+ myEntityManager.remove(next);
+ }
+ }
+ for (ResourceIndexedSearchParamNumber next : numberParams) {
+ myEntityManager.persist(next);
+ }
+
+ if (entity.isParamsDatePopulated()) {
+ for (ResourceIndexedSearchParamDate next : entity.getParamsDate()) {
+ myEntityManager.remove(next);
+ }
+ }
+ for (ResourceIndexedSearchParamDate next : dateParams) {
+ myEntityManager.persist(next);
+ }
+
+ if (entity.isHasLinks()) {
+ for (ResourceLink next : entity.getResourceLinks()) {
+ myEntityManager.remove(next);
+ }
+ }
+ for (ResourceLink next : links) {
+ myEntityManager.persist(next);
+ }
+
+ return entity;
+ }
+ });
+
+ return toMethodOutcome(savedEntity);
+ }
+
private Set addPredicateDate(Set thePids, List theOrParams) {
if (theOrParams == null || theOrParams.isEmpty()) {
return thePids;
@@ -266,19 +574,19 @@ public class FhirResourceDao
Predicate eq = builder.equal(from.get("myTargetResourcePid"), targetPid);
codePredicates.add(eq);
} else {
- // TODO: handle chain with resource type
String chain = myCtx.getResourceDefinition(myResourceType).getSearchParam(theParamName).getPath();
BaseRuntimeChildDefinition def = myCtx.newTerser().getDefinition(myResourceType, chain);
if (!(def instanceof RuntimeChildResourceDefinition)) {
throw new ConfigurationException("Property " + chain + " of type " + myResourceName + " is not a resource: " + def.getClass());
}
List> resourceTypes;
- if (ref.getType() == null) {
+ if (isBlank(ref.getResourceType())) {
RuntimeChildResourceDefinition resDef = (RuntimeChildResourceDefinition) def;
resourceTypes = resDef.getResourceTypes();
} else {
resourceTypes = new ArrayList<>();
- resourceTypes.add(ref.getType());
+ RuntimeResourceDefinition resDef = myCtx.getResourceDefinition(ref.getResourceType());
+ resourceTypes.add(resDef.getImplementingClass());
}
for (Class extends IResource> nextType : resourceTypes) {
RuntimeResourceDefinition typeDef = myCtx.getResourceDefinition(nextType);
@@ -313,7 +621,10 @@ public class FhirResourceDao
Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0]));
- Predicate type = builder.equal(from.get("mySourcePath"), myResourceName + "." + theParamName);
+ RuntimeSearchParam param = myCtx.getResourceDefinition(getResourceType()).getSearchParam(theParamName);
+ String path = param.getPath();
+
+ Predicate type = builder.equal(from.get("mySourcePath"), path);
if (pidsToRetain.size() > 0) {
Predicate inPids = (from.get("mySourceResourcePid").in(pidsToRetain));
cq.where(builder.and(type, inPids, masterCodePredicate));
@@ -422,53 +733,6 @@ public class FhirResourceDao
return new HashSet(q.getResultList());
}
- @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
- @Override
- public MethodOutcome create(T theResource) {
-
- final X entity = toEntity(theResource);
-
- entity.setPublished(new Date());
- entity.setUpdated(entity.getPublished());
-
- final List stringParams = extractSearchParamStrings(entity, theResource);
- final List tokenParams = extractSearchParamTokens(entity, theResource);
- final List numberParams = extractSearchParamNumber(entity, theResource);
- final List dateParams = extractSearchParamDates(entity, theResource);
- final List links = extractResourceLinks(entity, theResource);
-
- ourLog.info("Saving links: {}", links);
-
- TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager);
- template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
- template.setReadOnly(false);
- template.execute(new TransactionCallback() {
- @Override
- public X doInTransaction(TransactionStatus theStatus) {
- myEntityManager.persist(entity);
- for (ResourceIndexedSearchParamString next : stringParams) {
- myEntityManager.persist(next);
- }
- for (ResourceIndexedSearchParamToken next : tokenParams) {
- myEntityManager.persist(next);
- }
- for (ResourceIndexedSearchParamNumber next : numberParams) {
- myEntityManager.persist(next);
- }
- for (ResourceIndexedSearchParamDate next : dateParams) {
- myEntityManager.persist(next);
- }
- for (ResourceLink next : links) {
- myEntityManager.persist(next);
- }
- return entity;
- }
- });
-
- MethodOutcome outcome = toMethodOutcome(entity);
- return outcome;
- }
-
private List extractResourceLinks(X theEntity, T theResource) {
ArrayList retVal = new ArrayList();
@@ -533,6 +797,8 @@ public class FhirResourceDao
}
}
+ theEntity.setHasLinks(retVal.size() > 0);
+
return retVal;
}
@@ -580,6 +846,8 @@ public class FhirResourceDao
}
}
+ theEntity.setParamsDatePopulated(retVal.size() > 0);
+
return retVal;
}
@@ -608,8 +876,7 @@ public class FhirResourceDao
if (nextObject instanceof QuantityDt) {
QuantityDt nextValue = (QuantityDt) nextObject;
- ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(),
- nextValue.getUnits().getValue());
+ ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(), nextValue.getUnits().getValue());
nextEntity.setResource(theEntity, def.getName());
retVal.add(nextEntity);
} else {
@@ -622,6 +889,8 @@ public class FhirResourceDao
}
}
+ theEntity.setParamsNumberPopulated(retVal.size() > 0);
+
return retVal;
}
@@ -657,42 +926,57 @@ public class FhirResourceDao
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextValue.getValueAsString()), nextValue.getValueAsString());
nextEntity.setResource(theEntity, def.getName());
retVal.add(nextEntity);
- } else if (nextObject instanceof HumanNameDt) {
- ArrayList allNames = new ArrayList<>();
- allNames.addAll(((HumanNameDt) nextObject).getFamily());
- allNames.addAll(((HumanNameDt) nextObject).getGiven());
- for (StringDt nextName : allNames) {
- if (nextName.isEmpty()) {
- continue;
- }
- ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
- nextEntity.setResource(theEntity, def.getName());
- retVal.add(nextEntity);
- }
} else {
- if (!multiType) {
- throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
+ if (nextObject instanceof HumanNameDt) {
+ ArrayList allNames = new ArrayList<>();
+ HumanNameDt nextHumanName = (HumanNameDt) nextObject;
+ allNames.addAll(nextHumanName.getFamily());
+ allNames.addAll(nextHumanName.getGiven());
+ for (StringDt nextName : allNames) {
+ if (nextName.isEmpty()) {
+ continue;
+ }
+ ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
+ nextEntity.setResource(theEntity, def.getName());
+ retVal.add(nextEntity);
+ }
+ } else if (nextObject instanceof AddressDt) {
+ ArrayList allNames = new ArrayList<>();
+ AddressDt nextAddress = (AddressDt) nextObject;
+ allNames.addAll(nextAddress.getLine());
+ allNames.add(nextAddress.getCity());
+ allNames.add(nextAddress.getState());
+ allNames.add(nextAddress.getCountry());
+ allNames.add(nextAddress.getZip());
+ for (StringDt nextName : allNames) {
+ if (nextName.isEmpty()) {
+ continue;
+ }
+ ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
+ nextEntity.setResource(theEntity, def.getName());
+ retVal.add(nextEntity);
+ }
+ } else if (nextObject instanceof ContactDt) {
+ ContactDt nextContact = (ContactDt) nextObject;
+ if (nextContact.getValue().isEmpty() == false) {
+ ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextContact.getValue().getValueAsString()), nextContact.getValue().getValueAsString());
+ nextEntity.setResource(theEntity, def.getName());
+ retVal.add(nextEntity);
+ }
+ } else {
+ if (!multiType) {
+ throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
+ }
}
}
}
}
+
+ theEntity.setParamsStringPopulated(retVal.size() > 0);
return retVal;
}
- private String normalizeString(String theString) {
- char[] out = new char[theString.length()];
- theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
- int j = 0;
- for (int i = 0, n = theString.length(); i < n; ++i) {
- char c = theString.charAt(i);
- if (c <= '\u007F') {
- out[j++] = c;
- }
- }
- return new String(out).toUpperCase();
- }
-
private List extractSearchParamTokens(X theEntity, T theResource) {
ArrayList retVal = new ArrayList();
@@ -753,11 +1037,9 @@ public class FhirResourceDao
}
}
- return retVal;
- }
+ theEntity.setParamsTokenPopulated(retVal.size() > 0);
- public Class getResourceType() {
- return myResourceType;
+ return retVal;
}
private Map, IFhirResourceDao>> getResourceTypeToDao() {
@@ -772,39 +1054,17 @@ public class FhirResourceDao
return resourceTypeToDao;
}
- @Override
- public Class getTableType() {
- return myTableType;
- }
-
- @Transactional(propagation = Propagation.REQUIRED)
- @Override
- public List history(IdDt theId) {
- ArrayList retVal = new ArrayList();
-
- String resourceType = myCtx.getResourceDefinition(myResourceType).getName();
- TypedQuery q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class);
- q.setParameter("PID", theId.asLong());
- q.setParameter("RESTYPE", resourceType);
-
- // TypedQuery query =
- // myEntityManager.createQuery(criteriaQuery);
- List results = q.getResultList();
- for (ResourceHistoryTable next : results) {
- retVal.add(toResource(next));
+ private String normalizeString(String theString) {
+ char[] out = new char[theString.length()];
+ theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
+ int j = 0;
+ for (int i = 0, n = theString.length(); i < n; ++i) {
+ char c = theString.charAt(i);
+ if (c <= '\u007F') {
+ out[j++] = c;
+ }
}
-
- try {
- retVal.add(read(theId));
- } catch (ResourceNotFoundException e) {
- // ignore
- }
-
- if (retVal.isEmpty()) {
- throw new ResourceNotFoundException(theId);
- }
-
- return retVal;
+ return new String(out).toUpperCase();
}
private void populateResourceIntoEntity(T theResource, X retVal) {
@@ -820,22 +1080,6 @@ public class FhirResourceDao
}
- @PostConstruct
- public void postConstruct() throws Exception {
- myResourceType = myTableType.newInstance().getResourceType();
- myCtx = new FhirContext(myResourceType);
- myResourceName = myCtx.getResourceDefinition(myResourceType).getName();
- }
-
- @Transactional(propagation = Propagation.REQUIRED)
- @Override
- public T read(IdDt theId) {
- X entity = readEntity(theId);
-
- T retVal = toResource(entity);
- return retVal;
- }
-
private X readEntity(IdDt theId) {
X entity = (X) myEntityManager.find(myTableType, theId.asLong());
if (entity == null) {
@@ -844,132 +1088,6 @@ public class FhirResourceDao
return entity;
}
- @Override
- public List search(Map theParams) {
- SearchParameterMap map = new SearchParameterMap();
- for (Entry nextEntry : theParams.entrySet()) {
- map.put(nextEntry.getKey(), new ArrayList>());
- map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue()));
- }
- return search(map);
- }
-
- @Override
- public List search(String theParameterName, IQueryParameterType theValue) {
- return search(Collections.singletonMap(theParameterName, theValue));
- }
-
- @Override
- public Set searchForIds(Map theParams) {
- Map>> map = new HashMap>>();
- for (Entry nextEntry : theParams.entrySet()) {
- map.put(nextEntry.getKey(), new ArrayList>());
- map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue()));
- }
- return searchForIdsWithAndOr(map);
- }
-
- @Override
- public Set searchForIdsWithAndOr(Map>> theParams) {
- Map>> params = theParams;
- if (params == null) {
- params = Collections.emptyMap();
- }
-
- RuntimeResourceDefinition resourceDef = myCtx.getResourceDefinition(myResourceType);
-
- Set pids = new HashSet();
-
- for (Entry>> nextParamEntry : params.entrySet()) {
- String nextParamName = nextParamEntry.getKey();
- RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName);
- if (nextParamDef != null) {
- if (nextParamDef.getParamType() == SearchParamTypeEnum.TOKEN) {
- for (List nextAnd : nextParamEntry.getValue()) {
- pids = addPredicateToken(pids, nextAnd);
- if (pids.isEmpty()) {
- return new HashSet();
- }
- }
- } else if (nextParamDef.getParamType() == SearchParamTypeEnum.STRING) {
- for (List nextAnd : nextParamEntry.getValue()) {
- pids = addPredicateString(pids, nextAnd);
- if (pids.isEmpty()) {
- return new HashSet();
- }
- }
- } else if (nextParamDef.getParamType() == SearchParamTypeEnum.QUANTITY) {
- for (List nextAnd : nextParamEntry.getValue()) {
- pids = addPredicateQuantity(pids, nextAnd);
- if (pids.isEmpty()) {
- return new HashSet();
- }
- }
- } else if (nextParamDef.getParamType() == SearchParamTypeEnum.DATE) {
- for (List nextAnd : nextParamEntry.getValue()) {
- pids = addPredicateDate(pids, nextAnd);
- if (pids.isEmpty()) {
- return new HashSet();
- }
- }
- } else if (nextParamDef.getParamType() == SearchParamTypeEnum.REFERENCE) {
- for (List nextAnd : nextParamEntry.getValue()) {
- pids = addPredicateReference(nextParamName, pids, nextAnd);
- if (pids.isEmpty()) {
- return new HashSet();
- }
- }
- } else {
- throw new IllegalArgumentException("Don't know how to handle parameter of type: " + nextParamDef.getParamType());
- }
- }
- }
-
- return pids;
- }
-
- @Override
- public Set searchForIds(String theParameterName, IQueryParameterType theValue) {
- return searchForIds(Collections.singletonMap(theParameterName, theValue));
- }
-
- @Override
- public List search(SearchParameterMap theParams) {
-
- Set pids;
- if (theParams.isEmpty()) {
- pids = null;
- } else {
- pids = searchForIdsWithAndOr(theParams);
- if (pids.isEmpty()) {
- return new ArrayList<>();
- }
- }
-
- // Execute the query and make sure we return distinct results
- {
- CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
- CriteriaQuery cq = builder.createQuery(myTableType);
- Root from = cq.from(myTableType);
- if (!theParams.isEmpty()) {
- cq.where(from.get("myId").in(pids));
- }
- TypedQuery q = myEntityManager.createQuery(cq);
-
- List retVal = new ArrayList<>();
- for (X next : q.getResultList()) {
- T resource = toResource(next);
- retVal.add(resource);
- }
- return retVal;
- }
- }
-
- @Required
- public void setTableType(Class theTableType) {
- myTableType = theTableType;
- }
-
private X toEntity(T theResource) {
X retVal;
try {
@@ -1034,27 +1152,4 @@ public class FhirResourceDao
}
return retVal;
}
-
- @Transactional(propagation = Propagation.SUPPORTS)
- @Override
- public MethodOutcome update(final T theResource, final IdDt theId) {
- TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager);
- X savedEntity = template.execute(new TransactionCallback() {
- @Override
- public X doInTransaction(TransactionStatus theStatus) {
- final X entity = readEntity(theId);
- final ResourceHistoryTable existing = entity.toHistory(myCtx);
-
- populateResourceIntoEntity(theResource, entity);
- myEntityManager.persist(existing);
-
- entity.setUpdated(new Date());
- myEntityManager.persist(entity);
- return entity;
- }
- });
-
- return toMethodOutcome(savedEntity);
- }
-
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParameterMap.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParameterMap.java
index 3a8ce260a7c..64ea3207db4 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParameterMap.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchParameterMap.java
@@ -5,15 +5,17 @@ import java.util.HashMap;
import java.util.List;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
+import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
-import ca.uhn.fhir.rest.method.QualifiedParamList;
-import ca.uhn.fhir.rest.param.DateRangeParam;
public class SearchParameterMap extends HashMap>> {
private static final long serialVersionUID = 1L;
public void add(String theName, IQueryParameterType theParam) {
+ if (theParam == null) {
+ return;
+ }
if (!containsKey(theName)) {
put(theName, new ArrayList>());
}
@@ -22,13 +24,19 @@ public class SearchParameterMap extends HashMap>());
}
- for (QualifiedParamList next : theBirthdate.getValuesAsQueryTokens()) {
- next.get
+ for (IQueryParameterOr next : theAnd.getValuesAsQueryTokens()) {
+ if (next==null) {
+ continue;
+ }
+ get(theName).add(next.getValuesAsQueryTokens());
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceTable.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceTable.java
index a97e936f008..abcdf594f0c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceTable.java
@@ -28,17 +28,29 @@ import ca.uhn.fhir.model.primitive.IdDt;
@DiscriminatorColumn(name = "SVCVER_TYPE", length = 20, discriminatorType = DiscriminatorType.STRING)
public abstract class BaseResourceTable extends BaseHasResource {
+ @Column(name = "SP_HAS_LINKS")
+ private boolean myHasLinks;
+
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "RES_ID")
private Long myId;
+ @OneToMany(mappedBy = "myTargetResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
+ private Collection myIncomingResourceLinks;
+
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection myParamsDate;
@Column(name = "SP_DATE_PRESENT")
private boolean myParamsDatePopulated;
+ @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
+ private Collection myParamsNumber;
+
+ @Column(name = "SP_NUMBER_PRESENT")
+ private boolean myParamsNumberPopulated;
+
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection myParamsString;
@@ -51,6 +63,9 @@ public abstract class BaseResourceTable extends BaseHasReso
@Column(name = "SP_TOKEN_PRESENT")
private boolean myParamsTokenPopulated;
+ @OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
+ private Collection myResourceLinks;
+
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Collection myTags;
@@ -67,14 +82,14 @@ public abstract class BaseResourceTable extends BaseHasReso
getTags().add(new ResourceTag(this, theTerm, theLabel, theScheme));
}
- public Long getIdAsLong() {
- return myId;
- }
-
public IdDt getId() {
return new IdDt(myId);
}
+ public Long getIdAsLong() {
+ return myId;
+ }
+
public Collection getParamsDate() {
if (myParamsDate == null) {
myParamsDate = new ArrayList<>();
@@ -82,6 +97,13 @@ public abstract class BaseResourceTable extends BaseHasReso
return myParamsDate;
}
+ public Collection getParamsNumber() {
+ if (myParamsNumber == null) {
+ myParamsNumber = new ArrayList<>();
+ }
+ return myParamsNumber;
+ }
+
public Collection getParamsString() {
if (myParamsString == null) {
myParamsString = new ArrayList<>();
@@ -96,6 +118,13 @@ public abstract class BaseResourceTable extends BaseHasReso
return myParamsToken;
}
+ public Collection getResourceLinks() {
+ if (myResourceLinks == null) {
+ myResourceLinks = new ArrayList<>();
+ }
+ return myResourceLinks;
+ }
+
public abstract Class getResourceType();
public Collection getTags() {
@@ -109,10 +138,18 @@ public abstract class BaseResourceTable extends BaseHasReso
return new IdDt(myVersion);
}
+ public boolean isHasLinks() {
+ return myHasLinks;
+ }
+
public boolean isParamsDatePopulated() {
return myParamsDatePopulated;
}
+ public boolean isParamsNumberPopulated() {
+ return myParamsNumberPopulated;
+ }
+
public boolean isParamsStringPopulated() {
return myParamsStringPopulated;
}
@@ -121,6 +158,10 @@ public abstract class BaseResourceTable extends BaseHasReso
return myParamsTokenPopulated;
}
+ public void setHasLinks(boolean theHasLinks) {
+ myHasLinks = theHasLinks;
+ }
+
public void setId(IdDt theId) {
myId = theId.asLong();
}
@@ -133,6 +174,10 @@ public abstract class BaseResourceTable extends BaseHasReso
myParamsDatePopulated = theParamsDatePopulated;
}
+ public void setParamsNumberPopulated(boolean theParamsNumberPopulated) {
+ myParamsNumberPopulated = theParamsNumberPopulated;
+ }
+
public void setParamsString(Collection theParamsString) {
myParamsString = theParamsString;
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java
index 41ddadcaa8d..9d792c631b2 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceHistoryTag.java
@@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.entity;
import java.io.Serializable;
import javax.persistence.Entity;
+import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@@ -26,7 +27,7 @@ public class ResourceHistoryTag extends BaseTag implements Serializable {
@JoinColumn(name="RES_TYPE", referencedColumnName="RES_TYPE"),
@JoinColumn(name="PID", referencedColumnName="PID"),
@JoinColumn(name="VERSION", referencedColumnName="VERSION")
- })
+ }, foreignKey=@ForeignKey(name="FK_HT_RT"))
private ResourceHistoryTable myResourceHistory;
public ResourceHistoryTag() {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java
index e9f21801030..3741dfb978d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java
@@ -4,6 +4,8 @@ import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.ForeignKey;
+import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@@ -11,7 +13,7 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
-@Table(name = "IDX_SP_DATE")
+@Table(name = "SPIDX_DATE", indexes= {@Index(name="IDX_SP_DATE", columnList="myValueLow,myValueHigh")})
public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchParam {
private static final long serialVersionUID = 1L;
@@ -25,7 +27,7 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
public Date myValueLow;
@ManyToOne(optional = false)
- @JoinColumn(name = "RESOURCE_PID", nullable = false)
+ @JoinColumn(name = "RESOURCE_PID", nullable = false, foreignKey=@ForeignKey(name="FK_ISD_RESOURCE"))
private BaseResourceTable> myResource;
@Column(name = "RESOURCE_PID", insertable = false, updatable = false)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java
index da501c48934..a961a306337 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamNumber.java
@@ -4,12 +4,14 @@ import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.ForeignKey;
+import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
-@Table(name = "IDX_SP_NUMBER")
+@Table(name = "SPIDX_NUMBER", indexes= {@Index(name="IDX_SP_NUMBER", columnList="myValue")})
public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchParam {
private static final long serialVersionUID = 1L;
@@ -24,7 +26,7 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP
public BigDecimal myValue;
@ManyToOne(optional = false)
- @JoinColumn(name = "RESOURCE_PID", nullable = false)
+ @JoinColumn(name = "RESOURCE_PID", nullable = false, foreignKey=@ForeignKey(name="FK_ISN_RESOURCE"))
private BaseResourceTable> myResource;
@Column(name = "RESOURCE_PID", insertable = false, updatable = false)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
index 7fa8c48b6ad..a3e430db211 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
@@ -3,18 +3,20 @@ package ca.uhn.fhir.jpa.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
+import javax.persistence.ForeignKey;
+import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
-@Table(name = "IDX_SP_STRING")
+@Table(name = "SPIDX_STRING", indexes= {@Index(name="IDX_SP_STRING", columnList="myValueNormalized")})
public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchParam {
private static final long serialVersionUID = 1L;
@ManyToOne(optional = false, cascade = {}, fetch = FetchType.LAZY)
- @JoinColumn(name = "RESOURCE_PID", nullable = false)
+ @JoinColumn(name = "RESOURCE_PID", nullable = false, foreignKey=@ForeignKey(name="FK_ISS_RESOURCE"))
private BaseResourceTable> myResource;
@Column(name = "RESOURCE_PID", insertable=false, updatable=false)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java
index 753834a4be1..36112a1b1c7 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamToken.java
@@ -2,18 +2,20 @@ package ca.uhn.fhir.jpa.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.ForeignKey;
+import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
-@Table(name = "IDX_SP_TOKEN")
+@Table(name = "SPIDX_TOKEN", indexes= {@Index(name="IDX_SP_STRING", columnList="mySystem,myValue")})
public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchParam {
private static final long serialVersionUID = 1L;
@ManyToOne(optional = false)
- @JoinColumn(name = "RESOURCE_PID", nullable = false)
+ @JoinColumn(name = "RESOURCE_PID", nullable = false, foreignKey=@ForeignKey(name="FK_IST_RESOURCE"))
private BaseResourceTable> myResource;
@Column(name = "RESOURCE_PID", insertable=false, updatable=false)
@@ -33,6 +35,9 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
mySystem = theSystem;
}
+ public ResourceIndexedSearchParamToken() {
+ }
+
public ResourceIndexedSearchParamToken(String theName, String theSystem, String theValue) {
setName(theName);
setSystem(theSystem);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTag.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTag.java
index 4824f6b28bf..13a1e922e48 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTag.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTag.java
@@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.entity;
import javax.persistence.Entity;
+import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@@ -19,7 +20,7 @@ public class ResourceTag extends BaseTag {
private Long myId;
@ManyToOne(cascade= {})
- @JoinColumn(name = "RESOURCE_PID", nullable=false)
+ @JoinColumn(name = "RESOURCE_PID", nullable=false, foreignKey=@ForeignKey(name="FK_RESTAG_RESOURCE"))
private BaseResourceTable> myResource;
public ResourceTag() {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java
index 9b9cede8078..8384f35c7cc 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java
@@ -1,18 +1,14 @@
package ca.uhn.fhir.jpa.dao;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.hamcrest.core.StringContains;
import org.junit.AfterClass;
@@ -190,7 +186,7 @@ public class FhirResourceDaoTest {
found = ourPatientDao.search(Patient.SP_GENDER, new IdentifierDt(null, "F"));
assertEquals(0, found.size());
- Map>> map = new HashMap<>();
+ SearchParameterMap map = new SearchParameterMap();
map.put(Patient.SP_IDENTIFIER, new ArrayList>());
map.get(Patient.SP_IDENTIFIER).add(new ArrayList());
map.get(Patient.SP_IDENTIFIER).get(0).add(new IdentifierDt("urn:system", "001testPersistSearchParams"));
@@ -201,7 +197,7 @@ public class FhirResourceDaoTest {
assertEquals(1, found.size());
assertEquals(id, found.get(0).getId().asLong().longValue());
- map = new HashMap<>();
+ map = new SearchParameterMap();
map.put(Patient.SP_IDENTIFIER, new ArrayList>());
map.get(Patient.SP_IDENTIFIER).add(new ArrayList());
map.get(Patient.SP_IDENTIFIER).get(0).add(new IdentifierDt("urn:system", "001testPersistSearchParams"));
@@ -358,7 +354,7 @@ public class FhirResourceDaoTest {
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesYY"));
assertEquals(0,result.size());
- result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.class, Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01"));
+ result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01"));
assertEquals(1,result.size());
assertEquals(obsId01, result.get(0).getId());
@@ -505,6 +501,36 @@ public class FhirResourceDaoTest {
}
+
+ @Test
+ public void testUpdateMaintainsSearchParams() throws InterruptedException {
+ Patient p1 = new Patient();
+ p1.addIdentifier("urn:system", "testUpdateMaintainsSearchParamsAAA");
+ p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsAAA");
+ IdDt p1id = ourPatientDao.create(p1).getId();
+
+ Patient p2 = new Patient();
+ p2.addIdentifier("urn:system", "testUpdateMaintainsSearchParamsBBB");
+ p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsBBB");
+ IdDt p2id = ourPatientDao.create(p2).getId();
+
+ Set ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
+ assertEquals(1,ids.size());
+ assertThat(ids, contains(p1id.asLong()));
+
+ // Update the name
+ p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsBBB");
+ ourPatientDao.update(p1, p1id);
+
+ ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
+ assertEquals(0,ids.size());
+
+ ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsBBB"));
+ assertEquals(2,ids.size());
+
+ }
+
+
@AfterClass
public static void afterClass() {
ourCtx.close();
@@ -514,7 +540,7 @@ public class FhirResourceDaoTest {
@BeforeClass
public static void beforeClass() {
ourTestStarted = new Date();
- ourCtx = new ClassPathXmlApplicationContext("fhir-spring-test-config.xml");
+ ourCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml");
ourPatientDao = ourCtx.getBean("myPatientDao", IFhirResourceDao.class);
ourObservationDao = ourCtx.getBean("myObservationDao", IFhirResourceDao.class);
ourDiagnosticReportDao = ourCtx.getBean("myDiagnosticReportDao", IFhirResourceDao.class);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DeviceResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DeviceResourceTable.java
similarity index 78%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DeviceResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DeviceResourceTable.java
index 18ca1827988..4e999da5f88 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DeviceResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DeviceResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Device;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DiagnosticReportResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DiagnosticReportResourceTable.java
similarity index 81%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DiagnosticReportResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DiagnosticReportResourceTable.java
index 2d661b1f142..b2eaa1a06d3 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/DiagnosticReportResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/DiagnosticReportResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/LocationResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/LocationResourceTable.java
similarity index 79%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/LocationResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/LocationResourceTable.java
index 7b9cc3a1b8a..5bad4b1f238 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/LocationResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/LocationResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Location;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ObservationResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/ObservationResourceTable.java
similarity index 80%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ObservationResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/ObservationResourceTable.java
index 5b82911d292..edcafe8c641 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ObservationResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/ObservationResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Observation;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/OrganizationResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/OrganizationResourceTable.java
similarity index 80%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/OrganizationResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/OrganizationResourceTable.java
index 1d4c0493022..0dac1caf31d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/OrganizationResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/OrganizationResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Organization;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/PatientResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/PatientResourceTable.java
similarity index 79%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/PatientResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/PatientResourceTable.java
index 18de4f5a300..10b5dd0774c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/PatientResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/PatientResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Patient;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/QuestionnaireResourceTable.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/QuestionnaireResourceTable.java
similarity index 80%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/QuestionnaireResourceTable.java
rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/QuestionnaireResourceTable.java
index 5ee25fedac7..ca743e1dc1d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/QuestionnaireResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/testentity/QuestionnaireResourceTable.java
@@ -1,8 +1,9 @@
-package ca.uhn.fhir.jpa.entity;
+package ca.uhn.fhir.jpa.testentity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import ca.uhn.fhir.jpa.entity.BaseResourceTable;
import ca.uhn.fhir.model.dstu.resource.Questionnaire;
@Entity
diff --git a/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml b/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 00000000000..4b9f5e7cc2e
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,50 @@
+
+
+
+
+ org.hibernate.ejb.HibernatePersistence
+
+
+ ca.uhn.fhir.jpa.testentity.DeviceResourceTable
+ ca.uhn.fhir.jpa.testentity.DiagnosticReportResourceTable
+ ca.uhn.fhir.jpa.testentity.LocationResourceTable
+ ca.uhn.fhir.jpa.testentity.ObservationResourceTable
+ ca.uhn.fhir.jpa.testentity.OrganizationResourceTable
+ ca.uhn.fhir.jpa.testentity.PatientResourceTable
+ ca.uhn.fhir.jpa.testentity.QuestionnaireResourceTable
+ ca.uhn.fhir.jpa.testentity.QuestionnaireResourceTable
+
+ ca.uhn.fhir.jpa.entity.ResourceHistoryTable
+ ca.uhn.fhir.jpa.entity.ResourceHistoryTag
+ ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate
+ ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber
+ ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString
+ ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken
+ ca.uhn.fhir.jpa.entity.ResourceLink
+ ca.uhn.fhir.jpa.entity.ResourceTag
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-base/src/test/resources/fhir-spring-test-config.xml b/hapi-fhir-jpaserver-base/src/test/resources/fhir-jpabase-spring-test-config.xml
similarity index 85%
rename from hapi-fhir-jpaserver-base/src/test/resources/fhir-spring-test-config.xml
rename to hapi-fhir-jpaserver-base/src/test/resources/fhir-jpabase-spring-test-config.xml
index 63010aca6ba..6a6c05309ab 100644
--- a/hapi-fhir-jpaserver-base/src/test/resources/fhir-spring-test-config.xml
+++ b/hapi-fhir-jpaserver-base/src/test/resources/fhir-jpabase-spring-test-config.xml
@@ -14,22 +14,22 @@
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/hapi-fhir-jpaserver-test/.classpath b/hapi-fhir-jpaserver-test/.classpath
index 6bfebeceb5a..13d8e1e218a 100644
--- a/hapi-fhir-jpaserver-test/.classpath
+++ b/hapi-fhir-jpaserver-test/.classpath
@@ -1,6 +1,7 @@
+
diff --git a/hapi-fhir-jpaserver-test/pom.xml b/hapi-fhir-jpaserver-test/pom.xml
index 606f7a9d63b..e77d26d3904 100644
--- a/hapi-fhir-jpaserver-test/pom.xml
+++ b/hapi-fhir-jpaserver-test/pom.xml
@@ -80,6 +80,33 @@
+
+ ca.uhn.hapi.fhir
+ hapi-tinder-plugin
+ 0.3
+
+
+ buildclient
+
+ generate-jparest-server
+
+
+ ca.uhn.test.jpasrv
+
+ device
+ location
+ observation
+ organization
+ patient
+ practitioner
+ questionnaire
+ valueset
+
+ true
+
+
+
+
org.apache.maven.plugins
maven-deploy-plugin
diff --git a/hapi-fhir-jpaserver-test/src/main/java/ca/uhn/fhir/jpa/test/CompleteResourceProviderTest.java b/hapi-fhir-jpaserver-test/src/main/java/ca/uhn/fhir/jpa/test/CompleteResourceProviderTest.java
new file mode 100644
index 00000000000..66e0ed4be37
--- /dev/null
+++ b/hapi-fhir-jpaserver-test/src/main/java/ca/uhn/fhir/jpa/test/CompleteResourceProviderTest.java
@@ -0,0 +1,177 @@
+package ca.uhn.fhir.jpa.test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+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.jpa.dao.IFhirResourceDao;
+import ca.uhn.fhir.model.api.Bundle;
+import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
+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.dstu.resource.Questionnaire;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.rest.client.IGenericClient;
+import ca.uhn.fhir.rest.server.RestfulServer;
+import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
+import ca.uhn.fhir.rest.server.tester.RestfulServerTesterServlet;
+import ca.uhn.test.jpasrv.ObservationResourceProvider;
+import ca.uhn.test.jpasrv.OrganizationResourceProvider;
+import ca.uhn.test.jpasrv.PatientResourceProvider;
+
+public class CompleteResourceProviderTest {
+
+ private static ClassPathXmlApplicationContext ourAppCtx;
+ private static FhirContext ourCtx;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CompleteResourceProviderTest.class);
+
+ private static Server ourServer;
+ private static IFhirResourceDao patientDao;
+ private static IFhirResourceDao questionnaireDao;
+ private static IGenericClient ourClient;
+ private static IFhirResourceDao observationDao;
+
+ // @Test
+ // public void test01UploadTestResources() throws Exception {
+ //
+ // IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8888/fhir/context");
+ //
+ // File[] files = new File("src/test/resources/resources").listFiles(new PatternFilenameFilter(".*patient.*"));
+ // for (File file : files) {
+ // ourLog.info("Uploading: {}", file);
+ // Patient patient = ourCtx.newXmlParser().parseResource(Patient.class, new FileReader(file));
+ // client.create(patient);
+ // }
+ //
+ // files = new File("src/test/resources/resources").listFiles(new PatternFilenameFilter(".*questionnaire.*"));
+ // for (File file : files) {
+ // ourLog.info("Uploading: {}", file);
+ // Questionnaire patient = ourCtx.newXmlParser().parseResource(Questionnaire.class, new FileReader(file));
+ // client.create(patient);
+ // }
+ //
+ // }
+
+ @Test
+ public void testSearchByIdentifier() {
+ Patient p1 = new Patient();
+ p1.addIdentifier().setSystem("urn:system").setValue("testSearchByIdentifier01");
+ p1.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven01");
+ IdDt p1Id = ourClient.create(p1).getId();
+
+ Patient p2 = new Patient();
+ p2.addIdentifier().setSystem("urn:system").setValue("testSearchByIdentifier02");
+ p2.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven02");
+ ourClient.create(p2).getId();
+
+ Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01")).encodedJson().prettyPrint().execute();
+ assertEquals(1, actual.size());
+ assertEquals(p1Id, actual.getEntries().get(0).getId());
+
+ }
+
+ @Test
+ public void testSearchByResourceChain() {
+ Organization o1 = new Organization();
+ o1.setName("testSearchByResourceChainName01");
+ IdDt o1id = ourClient.create(o1).getId();
+
+ Patient p1 = new Patient();
+ p1.addIdentifier().setSystem("urn:system").setValue("testSearchByResourceChain01");
+ p1.addName().addFamily("testSearchByResourceChainFamily01").addGiven("testSearchByResourceChainGiven01");
+ p1.setManagingOrganization(new ResourceReferenceDt(Organization.class, o1id));
+ IdDt p1Id = ourClient.create(p1).getId();
+
+ //@formatter:off
+ Bundle actual = ourClient.search()
+ .forResource(Patient.class)
+ .where(Patient.PROVIDER.hasId(o1id))
+ .encodedJson().prettyPrint().execute();
+ //@formatter:on
+ assertEquals(1, actual.size());
+ assertEquals(p1Id, actual.getEntries().get(0).getId());
+
+ }
+
+ @Test
+ public void testInsertBadReference() {
+ Patient p1 = new Patient();
+ p1.addIdentifier().setSystem("urn:system").setValue("testSearchByResourceChain01");
+ p1.addName().addFamily("testSearchByResourceChainFamily01").addGiven("testSearchByResourceChainGiven01");
+ p1.setManagingOrganization(new ResourceReferenceDt(Organization.class, "132312323"));
+
+ try {
+ ourClient.create(p1).getId();
+ fail();
+ } catch (InvalidRequestException e) {
+ assertThat(e.getMessage(), containsString("Organization/132312323"));
+ }
+
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ ourServer.stop();
+ ourAppCtx.stop();
+ }
+
+ @SuppressWarnings("unchecked")
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ ourAppCtx = new ClassPathXmlApplicationContext("fhir-spring-test-config.xml");
+
+ patientDao = (IFhirResourceDao) ourAppCtx.getBean("myPatientDao", IFhirResourceDao.class);
+ PatientResourceProvider patientRp = new PatientResourceProvider();
+ patientRp.setDao(patientDao);
+
+ questionnaireDao = (IFhirResourceDao) ourAppCtx.getBean("myQuestionnaireDao", IFhirResourceDao.class);
+ QuestionnaireResourceProvider questionnaireRp = new QuestionnaireResourceProvider();
+ questionnaireRp.setDao(questionnaireDao);
+
+ observationDao = (IFhirResourceDao) ourAppCtx.getBean("myObservationDao", IFhirResourceDao.class);
+ ObservationResourceProvider observationRp = new ObservationResourceProvider();
+ observationRp.setDao(observationDao);
+
+ IFhirResourceDao