This commit is contained in:
parent
240decc210
commit
874b16207f
|
@ -991,7 +991,7 @@ public abstract class BaseParser implements IParser {
|
|||
|
||||
protected boolean shouldEncodeResourceId(IBaseResource theResource, EncodeContext theEncodeContext) {
|
||||
boolean retVal = true;
|
||||
if (isOmitResourceId()) {
|
||||
if (isOmitResourceId() && theEncodeContext.getPath().size() == 1) {
|
||||
retVal = false;
|
||||
} else {
|
||||
if (myDontEncodeElements != null) {
|
||||
|
|
|
@ -57,6 +57,11 @@ public interface IParser {
|
|||
*/
|
||||
IIdType getEncodeForceResourceId();
|
||||
|
||||
/**
|
||||
* When encoding, force this resource ID to be encoded as the resource ID
|
||||
*/
|
||||
IParser setEncodeForceResourceId(IIdType theForceResourceId);
|
||||
|
||||
/**
|
||||
* Which encoding does this parser instance produce?
|
||||
*/
|
||||
|
@ -70,6 +75,25 @@ public interface IParser {
|
|||
*/
|
||||
List<Class<? extends IBaseResource>> getPreferTypes();
|
||||
|
||||
/**
|
||||
* If set, when parsing resources the parser will try to use the given types when possible, in
|
||||
* the order that they are provided (from highest to lowest priority). For example, if a custom
|
||||
* type which declares to implement the Patient resource is passed in here, and the
|
||||
* parser is parsing a Bundle containing a Patient resource, the parser will use the given
|
||||
* custom type.
|
||||
* <p>
|
||||
* This feature is related to, but not the same as the
|
||||
* {@link FhirContext#setDefaultTypeForProfile(String, Class)} feature.
|
||||
* <code>setDefaultTypeForProfile</code> is used to specify a type to be used
|
||||
* when a resource explicitly declares support for a given profile. This
|
||||
* feature specifies a type to be used irrespective of the profile declaration
|
||||
* in the metadata statement.
|
||||
* </p>
|
||||
*
|
||||
* @param thePreferTypes The preferred types, or <code>null</code>
|
||||
*/
|
||||
void setPreferTypes(List<Class<? extends IBaseResource>> thePreferTypes);
|
||||
|
||||
/**
|
||||
* Returns true if resource IDs should be omitted
|
||||
*
|
||||
|
@ -78,6 +102,22 @@ public interface IParser {
|
|||
*/
|
||||
boolean isOmitResourceId();
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>) the ID of any resources being encoded will not be
|
||||
* included in the output. Note that this does not apply to contained resources, only to root resources. In other
|
||||
* words, if this is set to <code>true</code>, contained resources will still have local IDs but the outer/containing
|
||||
* ID will not have an ID.
|
||||
* <p>
|
||||
* If the resource being encoded is a Bundle or Parameters resource, this setting only applies to the
|
||||
* outer resource being encoded, not any resources contained wihthin.
|
||||
* </p>
|
||||
*
|
||||
* @param theOmitResourceId Should resource IDs be omitted
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @since 1.1
|
||||
*/
|
||||
IParser setOmitResourceId(boolean theOmitResourceId);
|
||||
|
||||
/**
|
||||
* If set to <code>true<code> (which is the default), resource references containing a version
|
||||
* will have the version removed when the resource is encoded. This is generally good behaviour because
|
||||
|
@ -92,6 +132,24 @@ public interface IParser {
|
|||
*/
|
||||
Boolean getStripVersionsFromReferences();
|
||||
|
||||
/**
|
||||
* If set to <code>true<code> (which is the default), resource references containing a version
|
||||
* will have the version removed when the resource is encoded. This is generally good behaviour because
|
||||
* in most situations, references from one resource to another should be to the resource by ID, not
|
||||
* by ID and version. In some cases though, it may be desirable to preserve the version in resource
|
||||
* links. In that case, this value should be set to <code>false</code>.
|
||||
* <p>
|
||||
* This method provides the ability to globally disable reference encoding. If finer-grained
|
||||
* control is needed, use {@link #setDontStripVersionsFromReferencesAtPaths(String...)}
|
||||
* </p>
|
||||
*
|
||||
* @param theStripVersionsFromReferences Set this to <code>false<code> to prevent the parser from removing resource versions from references (or <code>null</code> to apply the default setting from the {@link ParserOptions}
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
|
||||
* @see ParserOptions
|
||||
*/
|
||||
IParser setStripVersionsFromReferences(Boolean theStripVersionsFromReferences);
|
||||
|
||||
/**
|
||||
* Is the parser in "summary mode"? See {@link #setSummaryMode(boolean)} for information
|
||||
*
|
||||
|
@ -99,82 +157,75 @@ public interface IParser {
|
|||
*/
|
||||
boolean isSummaryMode();
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>) only elements marked by the FHIR specification as
|
||||
* being "summary elements" will be included.
|
||||
*
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setSummaryMode(boolean theSummaryMode);
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* (e.g. a custom type extending the default Patient class)
|
||||
* @param theReader
|
||||
* The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
|
||||
* @param theReader The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
|
||||
* @return A parsed resource
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
<T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* (e.g. a custom type extending the default Patient class)
|
||||
* @param theInputStream
|
||||
* The InputStream to parse input from, <b>with an implied charset of UTF-8</b>. Note that the InputStream will not be closed by the parser upon completion.
|
||||
* @param theInputStream The InputStream to parse input from, <b>with an implied charset of UTF-8</b>. Note that the InputStream will not be closed by the parser upon completion.
|
||||
* @return A parsed resource
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
<T extends IBaseResource> T parseResource(Class<T> theResourceType, InputStream theInputStream) throws DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
|
||||
* (e.g. a custom type extending the default Patient class)
|
||||
* @param theString
|
||||
* The string to parse
|
||||
* @param theString The string to parse
|
||||
* @return A parsed resource
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
<T extends IBaseResource> T parseResource(Class<T> theResourceType, String theString) throws DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theReader
|
||||
* The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
|
||||
* @param theReader The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
|
||||
* @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
|
||||
* {@link IAnyResource} depending on the specific FhirContext which created this parser.
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
IBaseResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theInputStream
|
||||
* The InputStream to parse input from (charset is assumed to be UTF-8).
|
||||
* @param theInputStream The InputStream to parse input from (charset is assumed to be UTF-8).
|
||||
* Note that the stream will not be closed by the parser upon completion.
|
||||
* @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
|
||||
* {@link IAnyResource} depending on the specific FhirContext which created this parser.
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
IBaseResource parseResource(InputStream theInputStream) throws ConfigurationException, DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a resource
|
||||
*
|
||||
* @param theMessageString
|
||||
* The string to parse
|
||||
* @param theMessageString The string to parse
|
||||
* @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
|
||||
* {@link IAnyResource} depending on the specific FhirContext which created this parser.
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
* @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
IBaseResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||
|
||||
|
@ -195,8 +246,7 @@ public interface IParser {
|
|||
* DSTU3+ mode.
|
||||
* </p>
|
||||
*
|
||||
* @param theDontEncodeElements
|
||||
* The elements to encode
|
||||
* @param theDontEncodeElements The elements to encode
|
||||
* @see #setEncodeElements(Set)
|
||||
*/
|
||||
IParser setDontEncodeElements(Set<String> theDontEncodeElements);
|
||||
|
@ -213,8 +263,7 @@ public interface IParser {
|
|||
* <li><b>*.(mandatory)</b> - This is a special case which causes any mandatory fields (min > 0) to be encoded</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param theEncodeElements
|
||||
* The elements to encode
|
||||
* @param theEncodeElements The elements to encode
|
||||
* @see #setDontEncodeElements(Set)
|
||||
*/
|
||||
IParser setEncodeElements(Set<String> theEncodeElements);
|
||||
|
@ -225,7 +274,7 @@ public interface IParser {
|
|||
* resource (typically a Bundle), but will be applied to any sub-resources
|
||||
* contained within it (i.e. search result resources in that bundle)
|
||||
*/
|
||||
void setEncodeElementsAppliesToChildResourcesOnly(boolean theEncodeElementsAppliesToChildResourcesOnly);
|
||||
boolean isEncodeElementsAppliesToChildResourcesOnly();
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is false), the values supplied
|
||||
|
@ -233,60 +282,20 @@ public interface IParser {
|
|||
* resource (typically a Bundle), but will be applied to any sub-resources
|
||||
* contained within it (i.e. search result resources in that bundle)
|
||||
*/
|
||||
boolean isEncodeElementsAppliesToChildResourcesOnly();
|
||||
|
||||
/**
|
||||
* When encoding, force this resource ID to be encoded as the resource ID
|
||||
*/
|
||||
IParser setEncodeForceResourceId(IIdType theForceResourceId);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>) the ID of any resources being encoded will not be
|
||||
* included in the output. Note that this does not apply to contained resources, only to root resources. In other
|
||||
* words, if this is set to <code>true</code>, contained resources will still have local IDs but the outer/containing
|
||||
* ID will not have an ID.
|
||||
*
|
||||
* @param theOmitResourceId
|
||||
* Should resource IDs be omitted
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @since 1.1
|
||||
*/
|
||||
IParser setOmitResourceId(boolean theOmitResourceId);
|
||||
void setEncodeElementsAppliesToChildResourcesOnly(boolean theEncodeElementsAppliesToChildResourcesOnly);
|
||||
|
||||
/**
|
||||
* Registers an error handler which will be invoked when any parse errors are found
|
||||
*
|
||||
* @param theErrorHandler
|
||||
* The error handler to set. Must not be null.
|
||||
* @param theErrorHandler The error handler to set. Must not be null.
|
||||
*/
|
||||
IParser setParserErrorHandler(IParserErrorHandler theErrorHandler);
|
||||
|
||||
/**
|
||||
* If set, when parsing resources the parser will try to use the given types when possible, in
|
||||
* the order that they are provided (from highest to lowest priority). For example, if a custom
|
||||
* type which declares to implement the Patient resource is passed in here, and the
|
||||
* parser is parsing a Bundle containing a Patient resource, the parser will use the given
|
||||
* custom type.
|
||||
* <p>
|
||||
* This feature is related to, but not the same as the
|
||||
* {@link FhirContext#setDefaultTypeForProfile(String, Class)} feature.
|
||||
* <code>setDefaultTypeForProfile</code> is used to specify a type to be used
|
||||
* when a resource explicitly declares support for a given profile. This
|
||||
* feature specifies a type to be used irrespective of the profile declaration
|
||||
* in the metadata statement.
|
||||
* </p>
|
||||
*
|
||||
* @param thePreferTypes
|
||||
* The preferred types, or <code>null</code>
|
||||
*/
|
||||
void setPreferTypes(List<Class<? extends IBaseResource>> thePreferTypes);
|
||||
|
||||
/**
|
||||
* Sets the "pretty print" flag, meaning that the parser will encode resources with human-readable spacing and
|
||||
* newlines between elements instead of condensing output as much as possible.
|
||||
*
|
||||
* @param thePrettyPrint
|
||||
* The flag
|
||||
* @param thePrettyPrint The flag
|
||||
* @return Returns an instance of <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setPrettyPrint(boolean thePrettyPrint);
|
||||
|
@ -295,61 +304,41 @@ public interface IParser {
|
|||
* Sets the server's base URL used by this parser. If a value is set, resource references will be turned into
|
||||
* relative references if they are provided as absolute URLs but have a base matching the given base.
|
||||
*
|
||||
* @param theUrl
|
||||
* The base URL, e.g. "http://example.com/base"
|
||||
* @param theUrl The base URL, e.g. "http://example.com/base"
|
||||
* @return Returns an instance of <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setServerBaseUrl(String theUrl);
|
||||
|
||||
/**
|
||||
* If set to <code>true<code> (which is the default), resource references containing a version
|
||||
* will have the version removed when the resource is encoded. This is generally good behaviour because
|
||||
* in most situations, references from one resource to another should be to the resource by ID, not
|
||||
* by ID and version. In some cases though, it may be desirable to preserve the version in resource
|
||||
* links. In that case, this value should be set to <code>false</code>.
|
||||
* <p>
|
||||
* This method provides the ability to globally disable reference encoding. If finer-grained
|
||||
* control is needed, use {@link #setDontStripVersionsFromReferencesAtPaths(String...)}
|
||||
* </p>
|
||||
*
|
||||
* @param theStripVersionsFromReferences
|
||||
* Set this to <code>false<code> to prevent the parser from removing resource versions from references (or <code>null</code> to apply the default setting from the {@link ParserOptions}
|
||||
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
|
||||
* @see ParserOptions
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setStripVersionsFromReferences(Boolean theStripVersionsFromReferences);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (which is the default), the Bundle.entry.fullUrl will override the Bundle.entry.resource's
|
||||
* resource id if the fullUrl is defined. This behavior happens when parsing the source data into a Bundle object. Set this
|
||||
* to <code>false</code> if this is not the desired behavior (e.g. the client code wishes to perform additional
|
||||
* validation checks between the fullUrl and the resource id).
|
||||
*
|
||||
* @param theOverrideResourceIdWithBundleEntryFullUrl
|
||||
* Set this to <code>false</code> to prevent the parser from overriding resource ids with the
|
||||
* @param theOverrideResourceIdWithBundleEntryFullUrl Set this to <code>false</code> to prevent the parser from overriding resource ids with the
|
||||
* Bundle.entry.fullUrl (or <code>null</code> to apply the default setting from the {@link ParserOptions})
|
||||
*
|
||||
* @see ParserOptions
|
||||
*
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @see ParserOptions
|
||||
*/
|
||||
IParser setOverrideResourceIdWithBundleEntryFullUrl(Boolean theOverrideResourceIdWithBundleEntryFullUrl);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>) only elements marked by the FHIR specification as
|
||||
* being "summary elements" will be included.
|
||||
*
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setSummaryMode(boolean theSummaryMode);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded
|
||||
* values.
|
||||
*/
|
||||
IParser setSuppressNarratives(boolean theSuppressNarratives);
|
||||
|
||||
/**
|
||||
* Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
|
||||
* or <code>null</code> if no value has been set for this parser (in which case the default from
|
||||
* the {@link ParserOptions} will be used}
|
||||
*
|
||||
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
|
||||
* @see #setStripVersionsFromReferences(Boolean)
|
||||
* @see ParserOptions
|
||||
*/
|
||||
Set<String> getDontStripVersionsFromReferencesAtPaths();
|
||||
|
||||
/**
|
||||
* If supplied value(s), any resource references at the specified paths will have their
|
||||
* resource versions encoded instead of being automatically stripped during the encoding
|
||||
|
@ -360,15 +349,14 @@ public interface IParser {
|
|||
* has been set to <code>true</code> (which is the default)
|
||||
* </p>
|
||||
*
|
||||
* @param thePaths
|
||||
* A collection of paths for which the resource versions will not be removed automatically
|
||||
* @param thePaths A collection of paths for which the resource versions will not be removed automatically
|
||||
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
|
||||
* only resource name and field names with dots separating is allowed here (no repetition
|
||||
* indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
|
||||
* set in the {@link ParserOptions}
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @see #setStripVersionsFromReferences(Boolean)
|
||||
* @see ParserOptions
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setDontStripVersionsFromReferencesAtPaths(String... thePaths);
|
||||
|
||||
|
@ -382,27 +370,15 @@ public interface IParser {
|
|||
* has been set to <code>true</code> (which is the default)
|
||||
* </p>
|
||||
*
|
||||
* @param thePaths
|
||||
* A collection of paths for which the resource versions will not be removed automatically
|
||||
* @param thePaths A collection of paths for which the resource versions will not be removed automatically
|
||||
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
|
||||
* only resource name and field names with dots separating is allowed here (no repetition
|
||||
* indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
|
||||
* set in the {@link ParserOptions}
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
* @see #setStripVersionsFromReferences(Boolean)
|
||||
* @see ParserOptions
|
||||
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
|
||||
*/
|
||||
IParser setDontStripVersionsFromReferencesAtPaths(Collection<String> thePaths);
|
||||
|
||||
/**
|
||||
* Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
|
||||
* or <code>null</code> if no value has been set for this parser (in which case the default from
|
||||
* the {@link ParserOptions} will be used}
|
||||
*
|
||||
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
|
||||
* @see #setStripVersionsFromReferences(Boolean)
|
||||
* @see ParserOptions
|
||||
*/
|
||||
Set<String> getDontStripVersionsFromReferencesAtPaths();
|
||||
|
||||
}
|
||||
|
|
|
@ -193,6 +193,14 @@ public class BundleBuilder {
|
|||
return new CreateBuilder(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry for a Collection bundle type
|
||||
*/
|
||||
public void addCollectionEntry(IBaseResource theResource) {
|
||||
setType("collection");
|
||||
addEntryAndReturnRequest(theResource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new entry and adds it to the bundle
|
||||
*
|
||||
|
@ -321,6 +329,16 @@ public class BundleBuilder {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value for <code>Bundle.type</code>. That this is a coded field so {@literal theType}
|
||||
* must be an actual valid value for this field or a {@link ca.uhn.fhir.parser.DataFormatException}
|
||||
* will be thrown.
|
||||
*/
|
||||
public void setType(String theType) {
|
||||
setBundleField("type", theType);
|
||||
}
|
||||
|
||||
|
||||
public static class UpdateBuilder {
|
||||
|
||||
private final IPrimitiveType<?> myUrl;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2297
|
||||
title: "When performing a FHIR create using the HAPI FHIR client, if the payload is a Bundle resource
|
||||
the individual resources in the Bundle had their IDs removed by the client during payload serialization.
|
||||
This has been corrected."
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import ca.uhn.fhir.util.BundleBuilder;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
|
@ -48,6 +49,7 @@ import org.apache.http.message.BasicHeader;
|
|||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hamcrest.core.StringEndsWith;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||
|
@ -73,6 +75,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.either;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
@ -206,6 +209,51 @@ public class ClientR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See #2297
|
||||
*/
|
||||
@Test
|
||||
public void testCreateBundlePreservesIds() throws Exception {
|
||||
|
||||
BundleBuilder bb = new BundleBuilder(ourCtx);
|
||||
bb.setType("collection");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/123");
|
||||
patient.addIdentifier().setSystem("urn:foo").setValue("bar");
|
||||
bb.addCollectionEntry(patient);
|
||||
|
||||
IBaseBundle inputBundle = bb.getBundle();
|
||||
inputBundle.setId("ABC");
|
||||
|
||||
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), 201, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://foo");
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
CapturingInterceptor interceptor = new CapturingInterceptor();
|
||||
client.registerInterceptor(interceptor);
|
||||
|
||||
client.create().resource(inputBundle).execute();
|
||||
|
||||
assertEquals("http://foo/Bundle?_format=json", ((ApacheHttpRequest) interceptor.getLastRequest()).getApacheRequest().getURI().toASCIIString());
|
||||
|
||||
assertEquals(HttpPost.class, capt.getValue().getClass());
|
||||
HttpPost post = (HttpPost) capt.getValue();
|
||||
String requestBody = IOUtils.toString(post.getEntity().getContent(), Charsets.UTF_8);
|
||||
ourLog.info("Request body: {}", requestBody);
|
||||
assertThat(requestBody, StringContains.containsString("{\"resourceType\":\"Patient\""));
|
||||
Bundle requestBundle = ourCtx.newJsonParser().parseResource(Bundle.class, requestBody);
|
||||
|
||||
assertEquals("123", requestBundle.getEntry().get(0).getResource().getIdElement().getIdPart());
|
||||
assertThat(requestBody, containsString("\"id\":\"123\""));
|
||||
assertThat(requestBody, not(containsString("\"id\":\"ABC\"")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Some servers (older ones?) return the resourcde you created instead of an OperationOutcome. We just need to ignore
|
||||
* it.
|
||||
|
|
Loading…
Reference in New Issue