diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java index a18f89243dc..9ec3fd8cc11 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java @@ -180,7 +180,13 @@ public class ServerConformanceProvider implements IServerConformanceProvider includes = new TreeSet(); + TreeSet includes = new TreeSet<>(); // Map nameToSearchParam = new HashMap(); @@ -273,7 +277,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider() { + resource.getInteraction().sort(new Comparator() { @Override public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { TypeRestfulInteraction o1 = theO1.getCode(); diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java index feb588dc076..41d1e70a285 100644 --- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java @@ -167,7 +167,13 @@ public class ServerConformanceProvider implements IServerConformanceProvider includes = new TreeSet(); diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java index 15757a4befb..2b49fb7b890 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java @@ -178,8 +178,14 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv // effort since the parser // needs to be modified to actually allow it - retVal.getImplementation().setDescription(myServerConfiguration.getImplementationDescription()); - retVal.setKind(CapabilityStatementKind.INSTANCE); + ServletContext servletContext = (ServletContext) (theRequest == null ? null : theRequest.getAttribute(RestfulServer.SERVLET_CONTEXT_ATTRIBUTE)); + String serverBase = myServerConfiguration.getServerAddressStrategy().determineServerBase(servletContext, theRequest); + retVal + .getImplementation() + .setUrl(serverBase) + .setDescription(myServerConfiguration.getImplementationDescription()); + + retVal.setKind(CapabilityStatementKind.INSTANCE); retVal.getSoftware().setName(myServerConfiguration.getServerName()); retVal.getSoftware().setVersion(myServerConfiguration.getServerVersion()); retVal.addFormat(Constants.CT_FHIR_XML_NEW); @@ -201,11 +207,9 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv String resourceName = nextEntry.getKey(); RuntimeResourceDefinition def = myServerConfiguration.getFhirContext().getResourceDefinition(resourceName); resource.getTypeElement().setValue(def.getName()); - ServletContext servletContext = (ServletContext) (theRequest == null ? null : theRequest.getAttribute(RestfulServer.SERVLET_CONTEXT_ATTRIBUTE)); - String serverBase = myServerConfiguration.getServerAddressStrategy().determineServerBase(servletContext, theRequest); resource.getProfile().setReference((def.getResourceProfile(serverBase))); - TreeSet includes = new TreeSet(); + TreeSet includes = new TreeSet<>(); // Map nameToSearchParam = new HashMap(); @@ -271,23 +275,23 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv } } - Collections.sort(resource.getInteraction(), new Comparator() { - @Override - public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { - TypeRestfulInteraction o1 = theO1.getCode(); - TypeRestfulInteraction o2 = theO2.getCode(); - if (o1 == null && o2 == null) { - return 0; - } - if (o1 == null) { - return 1; - } - if (o2 == null) { - return -1; - } - return o1.ordinal() - o2.ordinal(); - } - }); + resource.getInteraction().sort(new Comparator() { + @Override + public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { + TypeRestfulInteraction o1 = theO1.getCode(); + TypeRestfulInteraction o2 = theO2.getCode(); + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } + return o1.ordinal() - o2.ordinal(); + } + }); } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/MetadataCapabilityStatementDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/MetadataCapabilityStatementDstu3Test.java index 9a809a85a2f..3ae4cb8a230 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/MetadataCapabilityStatementDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/MetadataCapabilityStatementDstu3Test.java @@ -1,32 +1,5 @@ package ca.uhn.fhir.rest.server; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.stringContainsInOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.io.IOUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpRequestBase; -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.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider; -import org.hl7.fhir.dstu3.model.Patient; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.rest.annotation.OptionalParam; @@ -38,15 +11,116 @@ import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.VersionUtil; +import org.apache.commons.io.IOUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +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.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider; +import org.hl7.fhir.dstu3.model.CapabilityStatement; +import org.hl7.fhir.dstu3.model.Patient; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; public class MetadataCapabilityStatementDstu3Test { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MetadataCapabilityStatementDstu3Test.class); private static CloseableHttpClient ourClient; private static FhirContext ourCtx = FhirContext.forDstu3(); private static int ourPort; private static Server ourServer; private static RestfulServer ourServlet; - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MetadataCapabilityStatementDstu3Test.class); + + @Test + public void testElements() throws Exception { + String output; + + HttpRequestBase httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata?_elements=fhirVersion&_pretty=true"); + CloseableHttpResponse status = ourClient.execute(httpPost); + try { + output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + assertEquals(200, status.getStatusLine().getStatusCode()); + ourLog.info(output); + assertThat(output, containsString("", "SUBSETTED", "")); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + } + + @Test + public void testHttpMethods() throws Exception { + String output; + + HttpRequestBase httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata"); + CloseableHttpResponse status = ourClient.execute(httpPost); + try { + output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(output, containsString("", + output); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + + /* + * There is no @read on the RP below, so this should fail. Otherwise it + * would be interpreted as a read on ID "metadata" + */ + try { + httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient/metadata"); + status = ourClient.execute(httpPost); + output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + assertEquals(400, status.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + } + + @Test + public void testResponseContainsBaseUrl() throws Exception { + String output; + + HttpRequestBase httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata?_format=json"); + CloseableHttpResponse status = ourClient.execute(httpPost); + try { + output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + assertEquals(200, status.getStatusLine().getStatusCode()); + ourLog.info(output); + CapabilityStatement cs = ourCtx.newJsonParser().parseResource(CapabilityStatement.class, output); + + assertEquals("http://localhost:" + ourPort + "/", cs.getImplementation().getUrl()); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + } @Test public void testSummary() throws Exception { @@ -81,65 +155,6 @@ public class MetadataCapabilityStatementDstu3Test { } } - @Test - public void testElements() throws Exception { - String output; - - HttpRequestBase httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata?_elements=fhirVersion&_pretty=true"); - CloseableHttpResponse status = ourClient.execute(httpPost); - try { - output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - assertEquals(200, status.getStatusLine().getStatusCode()); - ourLog.info(output); - assertThat(output, containsString("", "SUBSETTED", "")); - } finally { - IOUtils.closeQuietly(status.getEntity().getContent()); - } - } - - @Test - public void testHttpMethods() throws Exception { - String output; - - HttpRequestBase httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata"); - CloseableHttpResponse status = ourClient.execute(httpPost); - try { - output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - assertEquals(200, status.getStatusLine().getStatusCode()); - assertThat(output, containsString("", - output); - } finally { - IOUtils.closeQuietly(status.getEntity().getContent()); - } - - /* - * There is no @read on the RP below, so this should fail. Otherwise it - * would be interpreted as a read on ID "metadata" - */ - try { - httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient/metadata"); - status = ourClient.execute(httpPost); - output = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - assertEquals(400, status.getStatusLine().getStatusCode()); - } finally { - IOUtils.closeQuietly(status.getEntity().getContent()); - } - } - @AfterClass public static void afterClassClearContext() throws Exception { ourServer.stop(); @@ -156,7 +171,7 @@ public class MetadataCapabilityStatementDstu3Test { ServletHandler proxyHandler = new ServletHandler(); ourServlet = new RestfulServer(ourCtx); ourServlet.setResourceProviders(patientProvider); - + ourServlet.setServerConformanceProvider(new ServerCapabilityStatementProvider(ourServlet)); ServletHolder servletHolder = new ServletHolder(ourServlet); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java index a410287cfda..6643bf03db1 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java @@ -171,7 +171,13 @@ public class ServerConformanceProvider implements IServerConformanceProvider includes = new TreeSet(); + TreeSet includes = new TreeSet<>(); // Map nameToSearchParam = // new HashMap() { + resource.getInteraction().sort(new Comparator() { @Override public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { TypeRestfulInteraction o1 = theO1.getCode(); diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java index 0dad86d875e..df711785dad 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java @@ -175,8 +175,14 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv retVal.setDateElement(conformanceDate()); retVal.setFhirVersion(FhirVersionEnum.R4.getFhirVersionString()); - retVal.getImplementation().setDescription(myServerConfiguration.getImplementationDescription()); - retVal.setKind(CapabilityStatementKind.INSTANCE); + ServletContext servletContext = (ServletContext) (theRequest == null ? null : theRequest.getAttribute(RestfulServer.SERVLET_CONTEXT_ATTRIBUTE)); + String serverBase = myServerConfiguration.getServerAddressStrategy().determineServerBase(servletContext, theRequest); + retVal + .getImplementation() + .setUrl(serverBase) + .setDescription(myServerConfiguration.getImplementationDescription()); + + retVal.setKind(CapabilityStatementKind.INSTANCE); retVal.getSoftware().setName(myServerConfiguration.getServerName()); retVal.getSoftware().setVersion(myServerConfiguration.getServerVersion()); retVal.addFormat(Constants.CT_FHIR_XML_NEW); @@ -198,11 +204,9 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv String resourceName = nextEntry.getKey(); RuntimeResourceDefinition def = myServerConfiguration.getFhirContext().getResourceDefinition(resourceName); resource.getTypeElement().setValue(def.getName()); - ServletContext servletContext = (ServletContext) (theRequest == null ? null : theRequest.getAttribute(RestfulServer.SERVLET_CONTEXT_ATTRIBUTE)); - String serverBase = myServerConfiguration.getServerAddressStrategy().determineServerBase(servletContext, theRequest); resource.getProfileElement().setValue(def.getResourceProfile(serverBase)); - TreeSet includes = new TreeSet(); + TreeSet includes = new TreeSet<>(); // Map nameToSearchParam = new HashMap(); @@ -268,23 +272,23 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv } } - Collections.sort(resource.getInteraction(), new Comparator() { - @Override - public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { - TypeRestfulInteraction o1 = theO1.getCode(); - TypeRestfulInteraction o2 = theO2.getCode(); - if (o1 == null && o2 == null) { - return 0; - } - if (o1 == null) { - return 1; - } - if (o2 == null) { - return -1; - } - return o1.ordinal() - o2.ordinal(); - } - }); + resource.getInteraction().sort(new Comparator() { + @Override + public int compare(ResourceInteractionComponent theO1, ResourceInteractionComponent theO2) { + TypeRestfulInteraction o1 = theO1.getCode(); + TypeRestfulInteraction o2 = theO2.getCode(); + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } + return o1.ordinal() - o2.ordinal(); + } + }); } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c13b75994ff..30babcbd954 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -29,6 +29,12 @@ may be stored as-is on the /Bundle endpoint. By default the following types are allowed: collection, document, message. + + CapabilityStatements generated by the server module will now include the server + base URL in the + CapabilityStatement.implementation.url]]> + field. +