Forward port #705, #708, and #710

Merge branch 'master' into hapi3_refactor
This commit is contained in:
James 2017-08-13 12:31:09 -04:00
commit 3b80779fd3
12 changed files with 91 additions and 66 deletions

View File

@ -140,6 +140,11 @@ public enum FhirVersionEnum {
String provideVersion();
}
/**
* This class attempts to read the FHIR version from the actual model
* classes in order to supply an accurate version string even over time
*
*/
private static class Dstu3Version implements IVersionProvider {
public Dstu3Version() {
@ -147,7 +152,7 @@ public enum FhirVersionEnum {
Class<?> c = Class.forName("org.hl7.fhir.dstu3.model.Constants");
myVersion = (String) c.getDeclaredField("VERSION").get(null);
} catch (Exception e) {
myVersion = "UNKNOWN";
myVersion = "3.0.1";
}
}
@ -167,7 +172,7 @@ public enum FhirVersionEnum {
Class<?> c = Class.forName("org.hl7.fhir.r4.model.Constants");
myVersion = (String) c.getDeclaredField("VERSION").get(null);
} catch (Exception e) {
myVersion = "UNKNOWN";
myVersion = "4.0.0";
}
}

View File

@ -46,7 +46,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
private FhirContext myContext;
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory>();
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<>();
private ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE;
private int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT;
private String myProxyUsername;
@ -82,9 +82,6 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/**
* Return the proxy username to authenticate with the HTTP proxy
*
* @param The
* proxy username
*/
protected String getProxyUsername() {
return myProxyUsername;
@ -92,9 +89,6 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/**
* Return the proxy password to authenticate with the HTTP proxy
*
* @param The
* proxy password
*/
protected String getProxyPassword() {
return myProxyPassword;
@ -128,8 +122,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
@SuppressWarnings("unchecked")
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
return proxy;
return (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
}
/**
@ -162,9 +155,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
myInvocationHandlers.put(theClientType, invocationHandler);
}
T proxy = instantiateProxy(theClientType, invocationHandler.newInvocationHandler(this));
return proxy;
return instantiateProxy(theClientType, invocationHandler.newInvocationHandler(this));
}
/**
@ -331,13 +322,14 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
FhirVersionEnum serverFhirVersionEnum = null;
if (StringUtils.isBlank(serverFhirVersionString)) {
// we'll be lenient and accept this
ourLog.debug("Server conformance statement does not indicate the FHIR version");
} else {
if (serverFhirVersionString.startsWith("0.4") || serverFhirVersionString.startsWith("0.5") || serverFhirVersionString.startsWith("1.0.")) {
if (serverFhirVersionString.equals(FhirVersionEnum.DSTU2.getFhirVersionString())) {
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
} else if (serverFhirVersionString.startsWith("3.0.")) {
} else if (serverFhirVersionString.equals(FhirVersionEnum.DSTU2_1.getFhirVersionString())) {
serverFhirVersionEnum = FhirVersionEnum.DSTU2_1;
} else if (serverFhirVersionString.equals(FhirVersionEnum.DSTU3.getFhirVersionString())) {
serverFhirVersionEnum = FhirVersionEnum.DSTU3;
} else if (serverFhirVersionString.startsWith("3.1.")) {
serverFhirVersionEnum = FhirVersionEnum.R4;
} else {
// we'll be lenient and accept this
ourLog.debug("Server conformance statement indicates unknown FHIR version: {}", serverFhirVersionString);

View File

@ -330,8 +330,9 @@ public class RestHookSubscriptionDstu2Interceptor extends BaseRestHookSubscripti
Subscription subscription = (Subscription) theResource;
if (subscription.getChannel() != null
&& subscription.getChannel().getTypeElement().getValueAsEnum() == SubscriptionChannelTypeEnum.REST_HOOK
&& subscription.getStatusElement().getValueAsEnum() == SubscriptionStatusEnum.ACTIVE) {
&& subscription.getStatusElement().getValueAsEnum() == SubscriptionStatusEnum.REQUESTED) {
removeLocalSubscription(subscription.getIdElement().getIdPart());
subscription.setStatus(SubscriptionStatusEnum.ACTIVE);
myRestHookSubscriptions.add(subscription);
ourLog.info("Subscription was added. Id: " + subscription.getId());
}

View File

@ -319,8 +319,9 @@ public class RestHookSubscriptionDstu3Interceptor extends BaseRestHookSubscripti
Subscription subscription = (Subscription) theResource;
if (subscription.getChannel() != null
&& subscription.getChannel().getType() == Subscription.SubscriptionChannelType.RESTHOOK
&& subscription.getStatus() == Subscription.SubscriptionStatus.ACTIVE) {
&& subscription.getStatus() == Subscription.SubscriptionStatus.REQUESTED) {
removeLocalSubscription(subscription.getIdElement().getIdPart());
subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE);
myRestHookSubscriptions.add(subscription);
ourLog.info("Subscription was added, id: {} - Have {}", subscription.getIdElement().getIdPart(), myRestHookSubscriptions.size());
}

View File

@ -24,6 +24,7 @@ import java.util.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.context.FhirVersionEnum;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -98,7 +99,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
retVal.setPublisher(myPublisher);
retVal.setDate(conformanceDate());
retVal.setFhirVersion("0.0.82-3059"); // TODO: pull from model
retVal.setFhirVersion(FhirVersionEnum.DSTU1.getFhirVersionString());
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser needs to be modified to actually allow it
retVal.getImplementation().setDescription(myServerConfiguration.getImplementationDescription());

View File

@ -28,6 +28,7 @@ import java.util.Map.Entry;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.context.FhirVersionEnum;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -162,7 +163,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
retVal.setPublisher(myPublisher);
retVal.setDate(conformanceDate());
retVal.setFhirVersion("1.0.2"); // TODO: pull from model
retVal.setFhirVersion(FhirVersionEnum.DSTU2.getFhirVersionString());
retVal.setAcceptUnknown(UnknownContentCodeEnum.UNKNOWN_EXTENSIONS); // TODO: make this configurable - this is a fairly big effort since the parser
// needs to be modified to actually allow it

View File

@ -68,7 +68,7 @@ public class ClientServerValidationDstu2Test {
@Test
public void testClientUsesInterceptors() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
conf.setFhirVersion("1.0.2");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -110,7 +110,7 @@ public class ClientServerValidationDstu2Test {
@Test
public void testForceConformanceCheck() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
conf.setFhirVersion("1.0.2");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -254,6 +254,44 @@ public class ClientServerValidationDstu2Test {
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}
@Test
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("1.0.2");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse = false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}
});
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}
@Test
public void testServerReturnsWrongVersionForDstu2() throws Exception {
Conformance conf = new Conformance();

View File

@ -30,6 +30,7 @@ import java.util.jar.Manifest;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.context.FhirVersionEnum;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.*;
import org.hl7.fhir.instance.model.Conformance.*;
@ -158,7 +159,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
retVal.setPublisher(myPublisher);
retVal.setDate(conformanceDate());
retVal.setFhirVersion("1.0.2"); // TODO: pull from model
retVal.setFhirVersion(FhirVersionEnum.DSTU2_HL7ORG.getFhirVersionString());
retVal.setAcceptUnknown(UnknownContentCode.EXTENSIONS); // TODO: make this configurable - this is a fairly big effort since the parser
// needs to be modified to actually allow it

View File

@ -57,46 +57,9 @@ public class ClientServerValidationTestHl7OrgDstu2 {
}
@Test
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse=false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}});
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}
@Test
public void testServerReturnsAppropriateVersionForDstu2_050() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
conf.setFhirVersion("1.0.2");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -133,7 +96,7 @@ public class ClientServerValidationTestHl7OrgDstu2 {
@Test
public void testServerReturnsWrongVersionForDstu2() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.80");
conf.setFhirVersion("0.0.82");
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -150,7 +113,7 @@ public class ClientServerValidationTestHl7OrgDstu2 {
fail();
} catch (FhirClientInappropriateForServerException e) {
String out = e.toString();
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.80\" which corresponds to DSTU1, but this client is configured to use DSTU2_HL7ORG (via the FhirContext)";
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.0.82\" which corresponds to DSTU1, but this client is configured to use DSTU2_HL7ORG (via the FhirContext)";
ourLog.info(out);
ourLog.info(want);
assertThat(out, containsString(want));

View File

@ -87,6 +87,7 @@ public class ClientServerValidationDstu1Test {
}
@Test
@Ignore
public void testServerReturnsWrongVersionDstu() throws Exception {
CapabilityStatement conf = new CapabilityStatement();
conf.setFhirVersion("0.4.0");

View File

@ -350,6 +350,14 @@
<id>dconlan</id>
<name>dconlan</name>
</developer>
<developer>
<id>psbrandt</id>
<name>Pascal Brandt</name>
</developer>
<developer>
<id>InfiniteLoop90</id>
<name>Clayton Bodendein</name>
</developer>
</developers>
<licenses>

View File

@ -283,6 +283,19 @@
Extensions on ID datatypes were not parsed or serialized correctly. Thanks to
Stephen Rivière for the pull request!
</action>
<action type="fix" issue="710">
Fix a bug in REST Hook Subscription interceptors which prevented subscriptions
from being activated. Thanks to Jeff Chung for the pull request!
</action>
<action type="fix" issue="708">
Fix broken links in usage pattern diagram on website. Thanks to
Pascal Brandt for the pull request!
</action>
<action type="fix" issue="706">
Fix incorrect FHIR Version Strings that were being outputted and verified in the
client for some versions of FHIR. Thanks to Clayton Bodendein for the
pull request!
</action>
</release>
<release version="2.5" date="2017-06-08">
<action type="fix">