Updates from DevDays
This commit is contained in:
parent
c78be081ef
commit
1fe3bb9ff0
|
@ -16,8 +16,13 @@ import ca.uhn.fhir.util.ElementUtil;
|
||||||
/**
|
/**
|
||||||
* Definition class for adding extensions to the built-in
|
* Definition class for adding extensions to the built-in
|
||||||
* Patient resource type.
|
* Patient resource type.
|
||||||
|
*
|
||||||
|
* Note the "profile" attribute below, which indicates the URL/ID of the
|
||||||
|
* profile implemented by this resource. You are not required to supply this,
|
||||||
|
* but if you do it will be automatically populated in the resource meta
|
||||||
|
* tag if the resource is returned by a server.
|
||||||
*/
|
*/
|
||||||
@ResourceDef(name="Patient")
|
@ResourceDef(name="Patient", profile="http://example.com/StructureDefinition/mypatient")
|
||||||
public class MyPatient extends Patient {
|
public class MyPatient extends Patient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.io.OutputStreamWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -52,6 +53,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
@ -59,6 +61,7 @@ import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.api.Tag;
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
@ -79,16 +82,30 @@ public class RestfulServerUtils {
|
||||||
|
|
||||||
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
|
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
|
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||||
if (tl == null) {
|
List<IdDt> tl = ResourceMetadataKeyEnum.PROFILES.get((IResource) theResource);
|
||||||
tl = new TagList();
|
if (tl == null) {
|
||||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
|
tl = new ArrayList<IdDt>();
|
||||||
}
|
ResourceMetadataKeyEnum.PROFILES.put((IResource) theResource, tl);
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
||||||
String profile = nextDef.getResourceProfile(theServerBase);
|
String profile = nextDef.getResourceProfile(theServerBase);
|
||||||
if (isNotBlank(profile)) {
|
if (isNotBlank(profile)) {
|
||||||
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
tl.add(new IdDt(profile));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
|
||||||
|
if (tl == null) {
|
||||||
|
tl = new TagList();
|
||||||
|
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
||||||
|
String profile = nextDef.getResourceProfile(theServerBase);
|
||||||
|
if (isNotBlank(profile)) {
|
||||||
|
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +150,8 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint, BundleTypeEnum theBundleType) {
|
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
|
||||||
|
BundleTypeEnum theBundleType) {
|
||||||
try {
|
try {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
b.append(theServerBase);
|
b.append(theServerBase);
|
||||||
|
@ -173,7 +191,7 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theBundleType != null) {
|
if (theBundleType != null) {
|
||||||
b.append('&');
|
b.append('&');
|
||||||
b.append(Constants.PARAM_BUNDLETYPE);
|
b.append(Constants.PARAM_BUNDLETYPE);
|
||||||
|
@ -223,8 +241,7 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns null if the request doesn't express that it wants FHIR. If it expresses that it wants
|
* Returns null if the request doesn't express that it wants FHIR. If it expresses that it wants XML and JSON equally, returns thePrefer.
|
||||||
* XML and JSON equally, returns thePrefer.
|
|
||||||
*/
|
*/
|
||||||
public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq, EncodingEnum thePrefer) {
|
public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq, EncodingEnum thePrefer) {
|
||||||
String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
|
String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
|
||||||
|
@ -258,11 +275,11 @@ public class RestfulServerUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startSpaceIndex == -1) {
|
if (startSpaceIndex == -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int endSpaceIndex = -1;
|
int endSpaceIndex = -1;
|
||||||
for (int i = startSpaceIndex; i < nextToken.length(); i++) {
|
for (int i = startSpaceIndex; i < nextToken.length(); i++) {
|
||||||
if (nextToken.charAt(i) == ' ' || nextToken.charAt(i) == ';') {
|
if (nextToken.charAt(i) == ' ' || nextToken.charAt(i) == ';') {
|
||||||
|
@ -270,7 +287,7 @@ public class RestfulServerUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float q = 1.0f;
|
float q = 1.0f;
|
||||||
EncodingEnum encoding;
|
EncodingEnum encoding;
|
||||||
boolean pretty = false;
|
boolean pretty = false;
|
||||||
|
@ -289,7 +306,7 @@ public class RestfulServerUtils {
|
||||||
int equalsIndex = nextQualifier.indexOf('=');
|
int equalsIndex = nextQualifier.indexOf('=');
|
||||||
if (equalsIndex != -1) {
|
if (equalsIndex != -1) {
|
||||||
String nextQualifierKey = nextQualifier.substring(0, equalsIndex).trim();
|
String nextQualifierKey = nextQualifier.substring(0, equalsIndex).trim();
|
||||||
String nextQualifierValue = nextQualifier.substring(equalsIndex+1, nextQualifier.length()).trim();
|
String nextQualifierValue = nextQualifier.substring(equalsIndex + 1, nextQualifier.length()).trim();
|
||||||
if (nextQualifierKey.equals("q")) {
|
if (nextQualifierKey.equals("q")) {
|
||||||
try {
|
try {
|
||||||
q = Float.parseFloat(nextQualifierValue);
|
q = Float.parseFloat(nextQualifierValue);
|
||||||
|
@ -308,46 +325,46 @@ public class RestfulServerUtils {
|
||||||
bestQ = q;
|
bestQ = q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Matcher m = ACCEPT_HEADER_PATTERN.matcher(nextAcceptHeaderValue);
|
// Matcher m = ACCEPT_HEADER_PATTERN.matcher(nextAcceptHeaderValue);
|
||||||
// float q = 1.0f;
|
// float q = 1.0f;
|
||||||
// while (m.find()) {
|
// while (m.find()) {
|
||||||
// String contentTypeGroup = m.group(1);
|
// String contentTypeGroup = m.group(1);
|
||||||
// EncodingEnum encoding = Constants.FORMAT_VAL_TO_ENCODING.get(contentTypeGroup);
|
// EncodingEnum encoding = Constants.FORMAT_VAL_TO_ENCODING.get(contentTypeGroup);
|
||||||
// if (encoding != null) {
|
// if (encoding != null) {
|
||||||
//
|
//
|
||||||
// String name = m.group(3);
|
// String name = m.group(3);
|
||||||
// String value = m.group(4);
|
// String value = m.group(4);
|
||||||
// if (name != null && value != null) {
|
// if (name != null && value != null) {
|
||||||
// if ("q".equals(name)) {
|
// if ("q".equals(name)) {
|
||||||
// try {
|
// try {
|
||||||
// q = Float.parseFloat(value);
|
// q = Float.parseFloat(value);
|
||||||
// q = Math.max(q, 0.0f);
|
// q = Math.max(q, 0.0f);
|
||||||
// } catch (NumberFormatException e) {
|
// } catch (NumberFormatException e) {
|
||||||
// ourLog.debug("Invalid Accept header q value: {}", value);
|
// ourLog.debug("Invalid Accept header q value: {}", value);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if (encoding != null) {
|
// if (encoding != null) {
|
||||||
// if (q > bestQ || (q == bestQ && encoding == thePrefer)) {
|
// if (q > bestQ || (q == bestQ && encoding == thePrefer)) {
|
||||||
// retVal = encoding;
|
// retVal = encoding;
|
||||||
// bestQ = q;
|
// bestQ = q;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if (!",".equals(m.group(5))) {
|
// if (!",".equals(m.group(5))) {
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -546,7 +563,7 @@ public class RestfulServerUtils {
|
||||||
|
|
||||||
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, String theServerBase, Set<SummaryEnum> theSummaryMode, boolean theRespondGzip,
|
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, String theServerBase, Set<SummaryEnum> theSummaryMode, boolean theRespondGzip,
|
||||||
boolean theRequestIsBrowser, RequestDetails theRequestDetails) throws IOException {
|
boolean theRequestIsBrowser, RequestDetails theRequestDetails) throws IOException {
|
||||||
assert!theServerBase.endsWith("/");
|
assert !theServerBase.endsWith("/");
|
||||||
|
|
||||||
theHttpResponse.setStatus(200);
|
theHttpResponse.setStatus(200);
|
||||||
|
|
||||||
|
@ -683,18 +700,18 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||||
// String countString = theRequest.getParameter(name);
|
// String countString = theRequest.getParameter(name);
|
||||||
// Integer count = null;
|
// Integer count = null;
|
||||||
// if (isNotBlank(countString)) {
|
// if (isNotBlank(countString)) {
|
||||||
// try {
|
// try {
|
||||||
// count = Integer.parseInt(countString);
|
// count = Integer.parseInt(countString);
|
||||||
// } catch (NumberFormatException e) {
|
// } catch (NumberFormatException e) {
|
||||||
// ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
// ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// return count;
|
// return count;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public static void validateResourceListNotNull(List<? extends IBaseResource> theResourceList) {
|
public static void validateResourceListNotNull(List<? extends IBaseResource> theResourceList) {
|
||||||
if (theResourceList == null) {
|
if (theResourceList == null) {
|
||||||
|
@ -718,7 +735,7 @@ public class RestfulServerUtils {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(retVal[0]);
|
return Integer.parseInt(retVal[0]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] {theParamName, retVal[0], e});
|
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e });
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
@ -33,31 +34,35 @@ import ca.uhn.fhir.util.PortUtil;
|
||||||
public class ReadDstu2Test {
|
public class ReadDstu2Test {
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
private static int ourPort;
|
|
||||||
private static Server ourServer;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReadDstu2Test.class);
|
||||||
/**
|
private static int ourPort;
|
||||||
* In DSTU2+ the resource ID appears in the resource body
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testReadXml() throws Exception {
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123&_format=xml");
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
private static Server ourServer;
|
||||||
assertThat(responseContent, containsString("p1ReadValue"));
|
|
||||||
assertThat(responseContent, containsString("p1ReadId"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In DSTU2+ the resource ID appears in the resource body
|
* In DSTU2+ the resource ID appears in the resource body
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testReadJson() throws Exception {
|
public void testReadJson() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123&_format=json");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123?_format=json");
|
||||||
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, containsString("p1ReadValue"));
|
||||||
|
assertThat(responseContent, containsString("p1ReadId"));
|
||||||
|
assertThat(responseContent, containsString("\"meta\":{\"profile\":[\"http://foo_profile\"]}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In DSTU2+ the resource ID appears in the resource body
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReadXml() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123&_format=xml");
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -101,19 +106,26 @@ public class ReadDstu2Test {
|
||||||
*/
|
*/
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
@Read
|
|
||||||
public Patient read(@IdParam IdDt theId) {
|
|
||||||
Patient p1 = new Patient();
|
|
||||||
p1.setId("p1ReadId");
|
|
||||||
p1.addIdentifier().setValue("p1ReadValue");
|
|
||||||
return p1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends IResource> getResourceType() {
|
public Class<? extends IResource> getResourceType() {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Read
|
||||||
|
public Patient read(@IdParam IdDt theId) {
|
||||||
|
Patient p1 = new MyPatient();
|
||||||
|
p1.setId("p1ReadId");
|
||||||
|
p1.addIdentifier().setValue("p1ReadValue");
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResourceDef(name = "Patient", profile = "http://foo_profile")
|
||||||
|
public static class MyPatient extends Patient {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue