Fix #446 - Don't give child resources the ID of the parent

This commit is contained in:
James Agnew 2016-09-16 15:01:14 -04:00
parent 12790d385c
commit f92c5a7232
4 changed files with 107 additions and 12 deletions

View File

@ -205,7 +205,7 @@ public class JsonParser extends BaseParser implements IParser {
JsonWriter eventWriter = createJsonWriter(theWriter); JsonWriter eventWriter = createJsonWriter(theWriter);
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null, false); encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null, false, false);
eventWriter.flush(); eventWriter.flush();
} }
@ -320,7 +320,7 @@ public class JsonParser extends BaseParser implements IParser {
IResource resource = nextEntry.getResource(); IResource resource = nextEntry.getResource();
if (resource != null && !resource.isEmpty() && !deleted) { if (resource != null && !resource.isEmpty() && !deleted) {
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource);
encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "content", false); encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "content", false, true);
} }
if (nextEntry.getSummary().isEmpty() == false) { if (nextEntry.getSummary().isEmpty() == false) {
@ -374,7 +374,7 @@ public class JsonParser extends BaseParser implements IParser {
IResource resource = nextEntry.getResource(); IResource resource = nextEntry.getResource();
if (resource != null && !resource.isEmpty() && !deleted) { if (resource != null && !resource.isEmpty() && !deleted) {
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(resource);
encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "resource", false); encodeResourceToJsonStreamWriter(resDef, resource, theEventWriter, "resource", false, true);
} }
if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) { if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
@ -551,7 +551,7 @@ public class JsonParser extends BaseParser implements IParser {
case RESOURCE: case RESOURCE:
IBaseResource resource = (IBaseResource) theNextValue; IBaseResource resource = (IBaseResource) theNextValue;
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource); RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, false); encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, false, true);
break; break;
case UNDECL_EXT: case UNDECL_EXT:
default: default:
@ -812,7 +812,7 @@ public class JsonParser extends BaseParser implements IParser {
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theParent); encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theParent);
} }
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonWriter theEventWriter, String theObjectNameOrNull, boolean theContainedResource) throws IOException { private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonWriter theEventWriter, String theObjectNameOrNull, boolean theContainedResource, boolean theSubResource) throws IOException {
IIdType resourceId = null; IIdType resourceId = null;
// if (theResource instanceof IResource) { // if (theResource instanceof IResource) {
// IResource res = (IResource) theResource; // IResource res = (IResource) theResource;
@ -843,7 +843,7 @@ public class JsonParser extends BaseParser implements IParser {
if (!theContainedResource) { if (!theContainedResource) {
if (super.shouldEncodeResourceId(theResource) == false) { if (super.shouldEncodeResourceId(theResource) == false) {
resourceId = null; resourceId = null;
} else if (getEncodeForceResourceId() != null) { } else if (!theSubResource && getEncodeForceResourceId() != null) {
resourceId = getEncodeForceResourceId(); resourceId = getEncodeForceResourceId();
} }
} }

View File

@ -174,7 +174,7 @@ public class XmlParser extends BaseParser implements IParser {
try { try {
eventWriter = createXmlWriter(theWriter); eventWriter = createXmlWriter(theWriter);
encodeResourceToXmlStreamWriter(theResource, eventWriter, false); encodeResourceToXmlStreamWriter(theResource, eventWriter, false, false);
eventWriter.flush(); eventWriter.flush();
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
throw new ConfigurationException("Failed to initialize STaX event factory", e); throw new ConfigurationException("Failed to initialize STaX event factory", e);
@ -384,7 +384,7 @@ public class XmlParser extends BaseParser implements IParser {
if (resource != null && !resource.isEmpty() && !deleted) { if (resource != null && !resource.isEmpty() && !deleted) {
eventWriter.writeStartElement("content"); eventWriter.writeStartElement("content");
eventWriter.writeAttribute("type", "text/xml"); eventWriter.writeAttribute("type", "text/xml");
encodeResourceToXmlStreamWriter(resource, eventWriter, false); encodeResourceToXmlStreamWriter(resource, eventWriter, false, true);
eventWriter.writeEndElement(); // content eventWriter.writeEndElement(); // content
} else { } else {
ourLog.debug("Bundle entry contains null resource"); ourLog.debug("Bundle entry contains null resource");
@ -447,7 +447,7 @@ public class XmlParser extends BaseParser implements IParser {
IResource resource = nextEntry.getResource(); IResource resource = nextEntry.getResource();
if (resource != null && !resource.isEmpty() && !deleted) { if (resource != null && !resource.isEmpty() && !deleted) {
theEventWriter.writeStartElement("resource"); theEventWriter.writeStartElement("resource");
encodeResourceToXmlStreamWriter(resource, theEventWriter, false); encodeResourceToXmlStreamWriter(resource, theEventWriter, false, true);
theEventWriter.writeEndElement(); // content theEventWriter.writeEndElement(); // content
} else { } else {
ourLog.debug("Bundle entry contains null resource"); ourLog.debug("Bundle entry contains null resource");
@ -557,7 +557,7 @@ public class XmlParser extends BaseParser implements IParser {
case RESOURCE: { case RESOURCE: {
theEventWriter.writeStartElement(childName); theEventWriter.writeStartElement(childName);
IBaseResource resource = (IBaseResource) theElement; IBaseResource resource = (IBaseResource) theElement;
encodeResourceToXmlStreamWriter(resource, theEventWriter, false); encodeResourceToXmlStreamWriter(resource, theEventWriter, false, true);
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
break; break;
} }
@ -711,7 +711,7 @@ public class XmlParser extends BaseParser implements IParser {
} }
} }
private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource) throws XMLStreamException, DataFormatException { private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource) throws XMLStreamException, DataFormatException {
IIdType resourceId = null; IIdType resourceId = null;
if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) { if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) {
@ -727,7 +727,7 @@ public class XmlParser extends BaseParser implements IParser {
if (!theIncludedResource) { if (!theIncludedResource) {
if (super.shouldEncodeResourceId(theResource) == false) { if (super.shouldEncodeResourceId(theResource) == false) {
resourceId = null; resourceId = null;
} else if (getEncodeForceResourceId() != null) { } else if (theSubResource == false && getEncodeForceResourceId() != null) {
resourceId = getEncodeForceResourceId(); resourceId = getEncodeForceResourceId();
} }
} }

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader; import java.io.StringReader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -26,6 +27,7 @@ import org.apache.http.ProtocolVersion;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine; import org.apache.http.message.BasicStatusLine;
@ -735,6 +737,93 @@ public class GenericClientDstu3Test {
} }
} }
@Test
public void testPutDoesntForceAllIdsXml() throws Exception {
IParser p = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.setId("PATIENT1");
patient.addName().addFamily("PATIENT1");
Bundle bundle = new Bundle();
bundle.setId("BUNDLE1");
bundle.addEntry().setResource(patient);
final String encoded = p.encodeResourceToString(bundle);
assertEquals("<Bundle xmlns=\"http://hl7.org/fhir\"><id value=\"BUNDLE1\"/><entry><resource><Patient xmlns=\"http://hl7.org/fhir\"><id value=\"PATIENT1\"/><name><family value=\"PATIENT1\"/></name></Patient></resource></entry></Bundle>", encoded);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
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<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
client
.update()
.resource(bundle)
.prefer(PreferReturnEnum.REPRESENTATION)
.execute();
HttpPut httpRequest = (HttpPut) capt.getValue();
assertEquals("http://example.com/fhir/Bundle/BUNDLE1", httpRequest.getURI().toASCIIString());
String requestString = IOUtils.toString(httpRequest.getEntity().getContent(), StandardCharsets.UTF_8);
assertEquals(encoded, requestString);
}
@Test
public void testPutDoesntForceAllIdsJson() throws Exception {
IParser p = ourCtx.newJsonParser();
Patient patient = new Patient();
patient.setId("PATIENT1");
patient.addName().addFamily("PATIENT1");
Bundle bundle = new Bundle();
bundle.setId("BUNDLE1");
bundle.addEntry().setResource(patient);
final String encoded = p.encodeResourceToString(bundle);
assertEquals("{\"resourceType\":\"Bundle\",\"id\":\"BUNDLE1\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"PATIENT1\",\"name\":[{\"family\":[\"PATIENT1\"]}]}}]}", encoded);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
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_JSON_NEW + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
client
.update()
.resource(bundle)
.prefer(PreferReturnEnum.REPRESENTATION)
.encodedJson()
.execute();
HttpPut httpRequest = (HttpPut) capt.getValue();
assertEquals("http://example.com/fhir/Bundle/BUNDLE1", httpRequest.getURI().toASCIIString());
String requestString = IOUtils.toString(httpRequest.getEntity().getContent(), StandardCharsets.UTF_8);
assertEquals(encoded, requestString);
}
@Test @Test
public void testResponseHasContentTypeMissing() throws Exception { public void testResponseHasContentTypeMissing() throws Exception {
IParser p = ourCtx.newXmlParser(); IParser p = ourCtx.newXmlParser();

View File

@ -49,6 +49,12 @@
part of the generated server conformance part of the generated server conformance
statement statement
</action> </action>
<action type="fix" issue="446">
When performing an update using the client on a resource that
contains other resources (e.g. Bundle update), all child resources in the
parent bundle were incorrectly given the ID of the parent. Thanks
to Filip Domazet for reporting!
</action>
</release> </release>
<release version="2.0" date="2016-08-30"> <release version="2.0" date="2016-08-30">
<action type="fix"> <action type="fix">