Fix #143 and fix #146 - Issues with resource references for non contained resources when parsing a DSTU2 bundle, and issues encoding contained resources when encoding JSON
This commit is contained in:
parent
18d45e7cc8
commit
461fdb50ce
|
@ -158,7 +158,7 @@ public abstract class BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
public void containResourcesForEncoding(IBaseResource theResource) {
|
||||
protected void containResourcesForEncoding(IBaseResource theResource) {
|
||||
ContainedResources contained = new ContainedResources();
|
||||
containResourcesForEncoding(contained, theResource, theResource);
|
||||
myContainedResources = contained;
|
||||
|
|
|
@ -457,7 +457,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
case RESOURCE:
|
||||
IBaseResource resource = (IBaseResource) theNextValue;
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
|
||||
encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, true);
|
||||
encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, false);
|
||||
break;
|
||||
case UNDECL_EXT:
|
||||
default:
|
||||
|
@ -632,12 +632,12 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||
boolean theIsSubElementWithinResource) throws IOException {
|
||||
boolean theContainedResource) throws IOException {
|
||||
String resourceId = null;
|
||||
if (theResource instanceof IResource) {
|
||||
IResource res = (IResource) theResource;
|
||||
if (StringUtils.isNotBlank(res.getId().getIdPart())) {
|
||||
if (theIsSubElementWithinResource) {
|
||||
if (theContainedResource) {
|
||||
resourceId = res.getId().getIdPart();
|
||||
} else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
resourceId = res.getId().getIdPart();
|
||||
|
@ -645,17 +645,17 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
} else if (theResource instanceof IAnyResource) {
|
||||
IAnyResource res = (IAnyResource) theResource;
|
||||
if (theIsSubElementWithinResource && StringUtils.isNotBlank(res.getId())) {
|
||||
if (theContainedResource && StringUtils.isNotBlank(res.getId())) {
|
||||
resourceId = res.getId();
|
||||
}
|
||||
}
|
||||
|
||||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theIsSubElementWithinResource, resourceId);
|
||||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);
|
||||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||
boolean theIsSubElementWithinResource, String theResourceId) throws IOException {
|
||||
if (!theIsSubElementWithinResource) {
|
||||
boolean theContainedResource, String theResourceId) throws IOException {
|
||||
if (!theContainedResource) {
|
||||
super.containResourcesForEncoding(theResource);
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
for (BaseCodingDt securityLabel : securityLabels) {
|
||||
theEventWriter.writeStartObject();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theIsSubElementWithinResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
|
@ -731,7 +731,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theEventWriter.write("contentType", bin.getContentType());
|
||||
theEventWriter.write("content", bin.getContentAsBase64());
|
||||
} else {
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource);
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||
}
|
||||
|
||||
theEventWriter.writeEnd();
|
||||
|
|
|
@ -30,8 +30,6 @@ import java.util.Map;
|
|||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
|
@ -39,8 +37,6 @@ import org.hl7.fhir.instance.model.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.ICompositeType;
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
|
@ -65,7 +61,6 @@ import ca.uhn.fhir.model.api.BundleEntry;
|
|||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IExtension;
|
||||
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||
import ca.uhn.fhir.model.api.IIdentifiableElement;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
|
@ -74,6 +69,7 @@ import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
|||
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.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -81,6 +77,7 @@ import ca.uhn.fhir.model.primitive.InstantDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.IModelVisitor;
|
||||
|
||||
class ParserState<T> {
|
||||
|
@ -1465,6 +1462,10 @@ class ParserState<T> {
|
|||
private class ElementCompositeState extends BaseState {
|
||||
|
||||
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
|
||||
public BaseRuntimeElementCompositeDefinition<?> getDefinition() {
|
||||
return myDefinition;
|
||||
}
|
||||
|
||||
private IBase myInstance;
|
||||
|
||||
public ElementCompositeState(PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, IBase theInstance) {
|
||||
|
@ -1570,8 +1571,13 @@ class ParserState<T> {
|
|||
return;
|
||||
}
|
||||
case RESOURCE: {
|
||||
if (myInstance instanceof IResource) {
|
||||
ParserState<T>.PreResourceStateHapi state = new PreResourceStateHapi(myInstance, child.getMutator(), null);
|
||||
push(state);
|
||||
} else {
|
||||
ParserState<T>.PreResourceStateHl7Org state = new PreResourceStateHl7Org(myInstance, child.getMutator(), null);
|
||||
push(state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case UNDECL_EXT:
|
||||
|
@ -1816,12 +1822,20 @@ class ParserState<T> {
|
|||
|
||||
private class PreResourceStateHapi extends PreResourceState {
|
||||
private BundleEntry myEntry;
|
||||
private Object myTarget;
|
||||
private IMutator myMutator;
|
||||
|
||||
public PreResourceStateHapi(BundleEntry theEntry, Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
public PreResourceStateHapi(Object theTarget, IMutator theMutator, Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
myTarget = theTarget;
|
||||
myMutator = theMutator;
|
||||
}
|
||||
|
||||
public PreResourceStateHapi(Class<? extends IBaseResource> theResourceType) {
|
||||
super(theResourceType);
|
||||
}
|
||||
|
@ -1849,12 +1863,17 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
super.enteringNewElement(theNamespaceURI, theLocalPart);
|
||||
if (myEntry != null) {
|
||||
myEntry.setResource((IResource) getCurrentElement());
|
||||
}
|
||||
if (myMutator != null) {
|
||||
myMutator.addValue(myTarget, getCurrentElement());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1976,7 +1995,10 @@ class ParserState<T> {
|
|||
|
||||
@Override
|
||||
public void wereBack() {
|
||||
myContext.newTerser().visit(myInstance, new IModelVisitor() {
|
||||
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
|
||||
|
||||
FhirTerser terser = myContext.newTerser();
|
||||
terser.visit(myInstance, new IModelVisitor() {
|
||||
|
||||
@Override
|
||||
public void acceptElement(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
|
||||
|
@ -2002,6 +2024,35 @@ class ParserState<T> {
|
|||
}
|
||||
});
|
||||
|
||||
if (bundle) {
|
||||
/*
|
||||
* Stitch together resource references
|
||||
*/
|
||||
Map<IdDt, IResource> idToResource = new HashMap<IdDt, IResource>();
|
||||
FhirTerser t = myContext.newTerser();
|
||||
List<IResource> resources = t.getAllPopulatedChildElementsOfType(myInstance, IResource.class);
|
||||
for (IResource next : resources) {
|
||||
IdDt id = next.getId();
|
||||
if (id != null && id.isEmpty() == false) {
|
||||
String resName = myContext.getResourceDefinition(next).getName();
|
||||
idToResource.put(id.withResourceType(resName).toUnqualifiedVersionless(), next);
|
||||
}
|
||||
}
|
||||
|
||||
for (IResource next : resources) {
|
||||
List<BaseResourceReferenceDt> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
|
||||
for (BaseResourceReferenceDt nextRef : refs) {
|
||||
if (nextRef.isEmpty() == false && nextRef.getReference() != null) {
|
||||
IResource target = idToResource.get(nextRef.getReference().toUnqualifiedVersionless());
|
||||
if (target != null) {
|
||||
nextRef.setResource(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2264,7 +2315,6 @@ class ParserState<T> {
|
|||
super.enteringNewElement(theNamespace, theChildName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ResourceStateHl7Org extends ElementCompositeState {
|
||||
|
|
|
@ -220,7 +220,7 @@ public class FhirTerser {
|
|||
|
||||
}
|
||||
|
||||
private <T extends IElement> void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
|
||||
private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
|
||||
theCallback.acceptElement(theElement, theChildDefinition, theDefinition);
|
||||
addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
|
||||
|
||||
|
@ -249,11 +249,6 @@ public class FhirTerser {
|
|||
case RESOURCE:
|
||||
case RESOURCE_BLOCK:
|
||||
case COMPOSITE_DATATYPE: {
|
||||
if (theChildDefinition instanceof RuntimeChildDirectResource) {
|
||||
// Don't descend into embedded resources
|
||||
return;
|
||||
}
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition;
|
||||
for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) {
|
||||
List<? extends IBase> values = nextChild.getAccessor().getValues(theElement);
|
||||
|
@ -286,7 +281,13 @@ public class FhirTerser {
|
|||
}
|
||||
throw new DataFormatException(b.toString());
|
||||
}
|
||||
visit(nextValue, nextChild, childElementDef, theCallback);
|
||||
|
||||
if (nextChild instanceof RuntimeChildDirectResource) {
|
||||
// Don't descend into embedded resources
|
||||
theCallback.acceptElement(nextValue, nextChild, childElementDef);
|
||||
} else {
|
||||
visit(nextValue, nextChild, childElementDef, theCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -18,6 +18,7 @@ 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.hamcrest.Matchers;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -63,8 +64,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(5, bundle.getEntries().size());
|
||||
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("4", bundle.getEntries().get(4).getId().getIdPart());
|
||||
assertEquals("0", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("4", bundle.getEntries().get(4).getResource().getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=5&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true", bundle.getLinkNext()
|
||||
.getValue());
|
||||
assertNull(bundle.getLinkPrevious().getValue());
|
||||
|
@ -79,8 +80,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newJsonParser().parseBundle(responseContent);
|
||||
assertEquals(5, bundle.getEntries().size());
|
||||
assertEquals("5", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("9", bundle.getEntries().get(4).getId().getIdPart());
|
||||
assertEquals("5", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("9", bundle.getEntries().get(4).getResource().getId().getIdPart());
|
||||
assertNull(bundle.getLinkNext().getValue());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=5&_format=json&_pretty=true", bundle.getLinkPrevious()
|
||||
.getValue());
|
||||
|
@ -104,8 +105,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("8", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("9", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals("8", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("9", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertNull(bundle.getLinkNext().getValue());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=3&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true", bundle.getLinkPrevious()
|
||||
.getValue());
|
||||
|
@ -131,8 +132,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals("0", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkNext().getValue());
|
||||
assertNull(bundle.getLinkPrevious().getValue());
|
||||
link = bundle.getLinkNext().getValue();
|
||||
|
@ -146,8 +147,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("2", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals("2", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkNext().getValue());
|
||||
assertEquals(base + '/' + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkSelf().getValue());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkPrevious().getValue());
|
||||
|
@ -175,9 +176,11 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml&_include=Patient.managingOrganization&_include=foo", bundle.getLinkNext().getValue());
|
||||
assertEquals("0", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertThat(bundle.getLinkNext().getValue(), Matchers.startsWith(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml"));
|
||||
assertThat(bundle.getLinkNext().getValue(), containsString("&_include=foo"));
|
||||
assertThat(bundle.getLinkNext().getValue(), containsString("&_include=Patient.managingOrganization"));
|
||||
assertNull(bundle.getLinkPrevious().getValue());
|
||||
link = bundle.getLinkNext().getValue();
|
||||
}
|
||||
|
@ -190,11 +193,19 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("2", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2&_format=xml&_include=Patient.managingOrganization&_include=foo", bundle.getLinkNext().getValue());
|
||||
assertEquals(base + '/' + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml&_include=Patient.managingOrganization&_include=foo", bundle.getLinkSelf().getValue());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2&_format=xml&_include=Patient.managingOrganization&_include=foo", bundle.getLinkPrevious().getValue());
|
||||
assertEquals("2", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertThat(bundle.getLinkNext().getValue(), Matchers.startsWith(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2&_format=xml"));
|
||||
assertThat(bundle.getLinkNext().getValue(), containsString("&_include=foo"));
|
||||
assertThat(bundle.getLinkNext().getValue(), containsString("&_include=Patient.managingOrganization"));
|
||||
|
||||
assertThat(bundle.getLinkSelf().getValue(), Matchers.startsWith(base + '/' + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml"));
|
||||
assertThat(bundle.getLinkSelf().getValue(), containsString("&_include=foo"));
|
||||
assertThat(bundle.getLinkSelf().getValue(), containsString("&_include=Patient.managingOrganization"));
|
||||
|
||||
assertThat(bundle.getLinkPrevious().getValue(), Matchers.startsWith(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2&_format=xml"));
|
||||
assertThat(bundle.getLinkPrevious().getValue(), containsString("&_include=foo"));
|
||||
assertThat(bundle.getLinkPrevious().getValue(), containsString("&_include=Patient.managingOrganization"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,8 +227,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals("0", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("1", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2", bundle.getLinkNext().getValue());
|
||||
assertNull(bundle.getLinkPrevious().getValue());
|
||||
link = bundle.getLinkNext().getValue();
|
||||
|
@ -231,8 +242,8 @@ public class PagingTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(2, bundle.getEntries().size());
|
||||
assertEquals("2", bundle.getEntries().get(0).getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getId().getIdPart());
|
||||
assertEquals("2", bundle.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals("3", bundle.getEntries().get(1).getResource().getId().getIdPart());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2", bundle.getLinkNext().getValue());
|
||||
assertEquals(base + '/' + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2", bundle.getLinkSelf().getValue());
|
||||
assertEquals(base + '?' + Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2", bundle.getLinkPrevious().getValue());
|
||||
|
|
|
@ -98,7 +98,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
|
||||
retVal.setPublisher(myPublisher);
|
||||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
retVal.setFhirVersion("0.4.0"); // TODO: pull from model
|
||||
retVal.setFhirVersion("0.5.0"); // TODO: pull from model
|
||||
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser
|
||||
// needs to be modified to actually allow it
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import net.sf.json.JSONSerializer;
|
|||
import net.sf.json.JsonConfig;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -468,6 +467,34 @@ public class JsonParserDstu2Test {
|
|||
assertNull(ResourceMetadataKeyEnum.PROFILES.get(patient));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for #146
|
||||
*/
|
||||
@Test
|
||||
public void testParseAndEncodeBundleFromXmlToJson() throws Exception {
|
||||
String content = IOUtils.toString(JsonParserDstu2Test.class.getResourceAsStream("/bundle-example2.xml"));
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, content);
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntry().get(0).getResource();
|
||||
assertEquals("#med", p.getMedication().getReference().getValue());
|
||||
|
||||
Medication m = (Medication) p.getMedication().getResource();
|
||||
assertNotNull(m);
|
||||
assertEquals("#med", m.getId().getValue());
|
||||
assertEquals(1, p.getContained().getContainedResources().size());
|
||||
assertSame(m, p.getContained().getContainedResources().get(0));
|
||||
|
||||
String reencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
assertThat(reencoded, containsString("contained"));
|
||||
|
||||
reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
assertThat(reencoded, containsString("contained"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseAndEncodeBundle() throws Exception {
|
||||
String content = IOUtils.toString(JsonParserDstu2Test.class.getResourceAsStream("/bundle-example.json"));
|
||||
|
@ -514,28 +541,26 @@ public class JsonParserDstu2Test {
|
|||
|
||||
@Test
|
||||
public void testParseAndEncodeBundleOldStyle() throws Exception {
|
||||
String content = IOUtils.toString(JsonParserDstu2Test.class.getResourceAsStream("/bundle-transaction.json"));
|
||||
String content = IOUtils.toString(JsonParserDstu2Test.class.getResourceAsStream("/bundle-example.json"));
|
||||
|
||||
Bundle parsed = ourCtx.newJsonParser().parseBundle(content);
|
||||
// assertEquals("http://example.com/base/Bundle/example/_history/1", parsed.getId().getValue());
|
||||
// assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
|
||||
// assertEquals("1", parsed.getId().getVersionIdPart());
|
||||
// assertEquals(new InstantDt("2014-08-18T01:43:30Z"),
|
||||
// parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
// assertEquals("searchset", parsed.getType().getValue());
|
||||
// assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
// assertEquals("http://example.com/base", parsed.getLinkBase().getValue());
|
||||
// assertEquals("https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2",
|
||||
// parsed.getLinkNext().getValue());
|
||||
// assertEquals("https://example.com/base/MedicationPrescription?patient=347&_include=MedicationPrescription.medication",
|
||||
// parsed.getLinkSelf().getValue());
|
||||
//
|
||||
// assertEquals(2, parsed.getEntries().size());
|
||||
//
|
||||
// MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
// assertEquals("Patient/347", p.getPatient().getReference().getValue());
|
||||
// assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
// assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
assertEquals("searchset", parsed.getType().getValue());
|
||||
assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
|
||||
assertEquals(2, parsed.getEntries().size());
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
assertEquals("Patient/347", p.getPatient().getReference().getValue());
|
||||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
Medication m = (Medication) parsed.getEntries().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertEquals("Medication/example", p.getMedication().getReference().getValue());
|
||||
assertSame(p.getMedication().getResource(), m);
|
||||
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
@ -579,6 +604,11 @@ public class JsonParserDstu2Test {
|
|||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
Medication m = (Medication) parsed.getEntry().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertEquals("Medication/example", p.getMedication().getReference().getValue());
|
||||
assertSame(p.getMedication().getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
||||
|
|
|
@ -405,6 +405,10 @@ public class XmlParserDstu2Test {
|
|||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
Medication m = (Medication) parsed.getEntries().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertSame(p.getMedication().getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
||||
|
@ -437,6 +441,10 @@ public class XmlParserDstu2Test {
|
|||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
// assertEquals("3123", p.getId().getValue());
|
||||
|
||||
Medication m = (Medication) parsed.getEntry().get(1).getResource();
|
||||
assertEquals("http://example.com/base/Medication/example", m.getId().getValue());
|
||||
assertSame(p.getMedication().getResource(), m);
|
||||
|
||||
String reencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(reencoded);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ClientServerValidationTestDstu2 {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
|
||||
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.4.0");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
@ -88,6 +88,43 @@ public class ClientServerValidationTestDstu2 {
|
|||
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");
|
||||
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 testServerReturnsWrongVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="09105af9-528c-47d0-a844-b7964236d6ff"/>
|
||||
<type value="searchset"/>
|
||||
<base value="http://fhirtest.uhn.ca/baseDstu2"/>
|
||||
<total value="1"/>
|
||||
<link>
|
||||
<relation value="self"/>
|
||||
<url value="http://10.160.2.151:28080/hapi-fhir-jpaserver/baseDstu2/MedicationPrescription?patient=13123&_format=xml"/>
|
||||
</link>
|
||||
<entry>
|
||||
<resource>
|
||||
<MedicationPrescription xmlns="http://hl7.org/fhir">
|
||||
<id value="20399"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2015-04-02T20:31:44.459-04:00"/>
|
||||
</meta>
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"> Thyroxine 0.112 MG Oral Tablet [Levoxyl] (rxnorm: 206485) </div>
|
||||
</text>
|
||||
<contained>
|
||||
<Medication xmlns="http://hl7.org/fhir">
|
||||
<id value="med"/>
|
||||
<name value="Thyroxine 0.112 MG Oral Tablet [Levoxyl]"/>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://www.nlm.nih.gov/research/umls/rxnorm"/>
|
||||
<code value="206485"/>
|
||||
<display value="Thyroxine 0.112 MG Oral Tablet [Levoxyl]"/>
|
||||
</coding>
|
||||
</code>
|
||||
</Medication>
|
||||
</contained>
|
||||
<status value="active"/>
|
||||
<patient>
|
||||
<reference value="Patient/13123"/>
|
||||
</patient>
|
||||
<medication>
|
||||
<reference value="#med"/>
|
||||
</medication>
|
||||
<dosageInstruction>
|
||||
<text value="1 daily"/>
|
||||
<doseQuantity>
|
||||
<value value="1"/>
|
||||
<units value="{tablet}"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="{tablet}"/>
|
||||
</doseQuantity>
|
||||
</dosageInstruction>
|
||||
<dispense>
|
||||
<numberOfRepeatsAllowed value="1"/>
|
||||
<quantity>
|
||||
<value value="90"/>
|
||||
<units value="{tablet}"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="{tablet}"/>
|
||||
</quantity>
|
||||
<expectedSupplyDuration>
|
||||
<value value="90"/>
|
||||
<units value="days"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="d"/>
|
||||
</expectedSupplyDuration>
|
||||
</dispense>
|
||||
</MedicationPrescription>
|
||||
</resource>
|
||||
<search>
|
||||
<mode value="match"/>
|
||||
</search>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -102,6 +102,18 @@
|
|||
server behind an Apache proxy (e.g. for load balancing or other reasons).
|
||||
Thanks to Bill de Beaubien for contributing!
|
||||
</action>
|
||||
<action type="fix" issue="143">
|
||||
Resource references between separate resources found in a single
|
||||
bundle did not get populated with the actual resource when parsing a
|
||||
DSTU2 style bundle. Thanks to Nick Peterson for reporting and figuring
|
||||
out why none of our unit tests were actually catching the problem!
|
||||
</action>
|
||||
<action type="fix" issue="146">
|
||||
JSON encoder did not encode contained resources when encoding
|
||||
a DSTU2 style bundle. Thanks to Mohammad Jafari and baopingle
|
||||
for all of their help in tracking this issue down and developing
|
||||
useful unit tests to demonstrate it.
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.9" date="2015-Mar-14">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue