Clean up encoding of contained resources so that resources are not
modified as a part of the encoding
This commit is contained in:
parent
507ea9bedf
commit
2a9d92df7a
|
@ -96,6 +96,14 @@
|
|||
have also caused resource validation to fail occasionally on these platforms as well.
|
||||
Thanks to Bill de Beaubien for reporting!
|
||||
</action>
|
||||
<action type="fix">
|
||||
toString() method on TokenParam was incorrectly showing the system as the value.
|
||||
Thanks to Bill de Beaubien for reporting!
|
||||
</action>
|
||||
<action type="update">
|
||||
Documentation on contained resources contained a typo and did not actually produce contained resources. Thanks
|
||||
to David Hay of Orion Health for reporting!
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.6" date="2014-Sep-08" description="This release brings a number of new features and bug fixes!">
|
||||
<!--
|
||||
|
|
|
@ -201,6 +201,9 @@ public class FhirContext {
|
|||
* Create and return a new JSON parser.
|
||||
*
|
||||
* <p>
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or every message being parsed/encoded.
|
||||
* </p>
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed without incurring any performance penalty
|
||||
* </p>
|
||||
*/
|
||||
|
@ -261,6 +264,9 @@ public class FhirContext {
|
|||
* Create and return a new XML parser.
|
||||
*
|
||||
* <p>
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or every message being parsed/encoded.
|
||||
* </p>
|
||||
* <p>
|
||||
* Performance Note: <b>This method is cheap</b> to call, and may be called once for every message being processed without incurring any performance penalty
|
||||
* </p>
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,9 @@ import java.io.Reader;
|
|||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -45,29 +47,60 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
|
||||
public abstract class BaseParser implements IParser {
|
||||
|
||||
private boolean mySuppressNarratives;
|
||||
private ContainedResources myContainedResources;
|
||||
private FhirContext myContext;
|
||||
private boolean mySuppressNarratives;
|
||||
|
||||
public BaseParser(FhirContext theContext) {
|
||||
myContext = theContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagList parseTagList(String theString) {
|
||||
return parseTagList(new StringReader(theString));
|
||||
private void containResourcesForEncoding(ContainedResources theContained, IResource theResource, IResource theTarget) {
|
||||
List<ResourceReferenceDt> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, ResourceReferenceDt.class);
|
||||
|
||||
Set<String> allIds = new HashSet<String>();
|
||||
|
||||
for (IResource next : theTarget.getContained().getContainedResources()) {
|
||||
String nextId = next.getId().getValue();
|
||||
if (StringUtils.isNotBlank(nextId)) {
|
||||
allIds.add(nextId);
|
||||
}
|
||||
}
|
||||
|
||||
for (ResourceReferenceDt next : allElements) {
|
||||
IResource resource = next.getResource();
|
||||
if (resource != null) {
|
||||
if (resource.getId().isEmpty()) {
|
||||
theContained.addContained(resource);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
containResourcesForEncoding(theContained, resource, theTarget);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Override
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
||||
StringReader reader = new StringReader(theMessageString);
|
||||
return (T) parseResource(theResourceType, reader);
|
||||
public void containResourcesForEncoding(IResource theResource) {
|
||||
ContainedResources contained = new ContainedResources();
|
||||
containResourcesForEncoding(contained, theResource, theResource);
|
||||
myContainedResources = contained;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle parseBundle(String theXml) throws ConfigurationException, DataFormatException {
|
||||
StringReader reader = new StringReader(theXml);
|
||||
return parseBundle(reader);
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
|
||||
if (theBundle == null) {
|
||||
throw new NullPointerException("Bundle can not be null");
|
||||
}
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
encodeBundleToWriter(theBundle, stringWriter);
|
||||
} catch (IOException e) {
|
||||
throw new Error("Encountered IOException during write to string - This should not happen!");
|
||||
}
|
||||
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,24 +125,15 @@ public abstract class BaseParser implements IParser {
|
|||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
|
||||
if (theBundle == null) {
|
||||
throw new NullPointerException("Bundle can not be null");
|
||||
}
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
encodeBundleToWriter(theBundle, stringWriter);
|
||||
} catch (IOException e) {
|
||||
throw new Error("Encountered IOException during write to string - This should not happen!");
|
||||
}
|
||||
|
||||
return stringWriter.toString();
|
||||
ContainedResources getContainedResources() {
|
||||
return myContainedResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException {
|
||||
return parseResource(null, theMessageString);
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded values.
|
||||
*/
|
||||
public boolean getSuppressNarratives() {
|
||||
return mySuppressNarratives;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,49 +141,38 @@ public abstract class BaseParser implements IParser {
|
|||
return parseBundle(null, theReader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle parseBundle(String theXml) throws ConfigurationException, DataFormatException {
|
||||
StringReader reader = new StringReader(theXml);
|
||||
return parseBundle(reader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Override
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
||||
StringReader reader = new StringReader(theMessageString);
|
||||
return (T) parseResource(theResourceType, reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
|
||||
return parseResource(null, theReader);
|
||||
}
|
||||
|
||||
public void containResourcesForEncoding(IResource theResource) {
|
||||
containResourcesForEncoding(theResource, theResource);
|
||||
@Override
|
||||
public IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException {
|
||||
return parseResource(null, theMessageString);
|
||||
}
|
||||
|
||||
private long myNextContainedId = 1;
|
||||
|
||||
private void containResourcesForEncoding(IResource theResource, IResource theTarget) {
|
||||
List<ResourceReferenceDt> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, ResourceReferenceDt.class);
|
||||
|
||||
Set<String> allIds = new HashSet<String>();
|
||||
|
||||
for (IResource next : theTarget.getContained().getContainedResources()) {
|
||||
String nextId = next.getId().getValue();
|
||||
if (StringUtils.isNotBlank(nextId)) {
|
||||
allIds.add(nextId);
|
||||
}
|
||||
}
|
||||
|
||||
for (ResourceReferenceDt next : allElements) {
|
||||
IResource resource = next.getResource();
|
||||
if (resource != null) {
|
||||
if (resource.getId().isEmpty()) { // TODO: make this configurable between the two below (and something else?)
|
||||
resource.setId(new IdDt(myNextContainedId++));
|
||||
// resource.setId(new IdDt(UUID.randomUUID().toString()));
|
||||
}
|
||||
|
||||
String nextResourceId = resource.getId().getValue();
|
||||
if (!allIds.contains(nextResourceId)) {
|
||||
theTarget.getContained().getContainedResources().add(resource);
|
||||
allIds.add(resource.getId().getValue());
|
||||
}
|
||||
|
||||
next.setReference("#" + resource.getId().getValue());
|
||||
|
||||
containResourcesForEncoding(resource, theTarget);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public TagList parseTagList(String theString) {
|
||||
return parseTagList(new StringReader(theString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IParser setSuppressNarratives(boolean theSuppressNarratives) {
|
||||
mySuppressNarratives = theSuppressNarratives;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void throwExceptionForUnknownChildType(BaseRuntimeChildDefinition nextChild, Class<? extends IElement> type) {
|
||||
|
@ -178,18 +191,37 @@ public abstract class BaseParser implements IParser {
|
|||
throw new DataFormatException(nextChild + " has no child of type " + type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IParser setSuppressNarratives(boolean theSuppressNarratives) {
|
||||
mySuppressNarratives = theSuppressNarratives;
|
||||
return this;
|
||||
}
|
||||
static class ContainedResources {
|
||||
private long myNextContainedId = 1;
|
||||
|
||||
private IdentityHashMap<IResource, IdDt> myResourceToId = new IdentityHashMap<IResource, IdDt>();
|
||||
private List<IResource> myResources = new ArrayList<IResource>();
|
||||
|
||||
public void addContained(IResource theResource) {
|
||||
if (myResourceToId.containsKey(theResource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: make this configurable between the two below (and something else?)
|
||||
IdDt newId = new IdDt(myNextContainedId++);
|
||||
// newId = new IdDt(UUID.randomUUID().toString());
|
||||
|
||||
myResourceToId.put(theResource, newId);
|
||||
myResources.add(theResource);
|
||||
}
|
||||
|
||||
public List<IResource> getContainedResources() {
|
||||
return myResources;
|
||||
}
|
||||
|
||||
public IdDt getResourceId(IResource theResource) {
|
||||
return myResourceToId.get(theResource);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return myResourceToId.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives
|
||||
* will not be included in the encoded values.
|
||||
*/
|
||||
public boolean getSuppressNarratives() {
|
||||
return mySuppressNarratives;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,12 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or every message being parsed/encoded.
|
||||
* </p>
|
||||
*/
|
||||
public interface IParser {
|
||||
|
||||
String encodeBundleToString(Bundle theBundle) throws DataFormatException;
|
||||
|
@ -40,26 +46,24 @@ public interface IParser {
|
|||
void encodeResourceToWriter(IResource theResource, Writer theWriter) throws IOException, DataFormatException;
|
||||
|
||||
/**
|
||||
* Encodes a tag list, as defined in the <a
|
||||
* href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR
|
||||
* Specification</a>.
|
||||
* Encodes a tag list, as defined in the <a href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR Specification</a>.
|
||||
*
|
||||
* @param theTagList The tag list to encode. Must not be null.
|
||||
* @param theTagList
|
||||
* The tag list to encode. Must not be null.
|
||||
* @return An encoded tag list
|
||||
*/
|
||||
String encodeTagListToString(TagList theTagList);
|
||||
|
||||
/**
|
||||
* Encodes a tag list, as defined in the <a
|
||||
* href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR
|
||||
* Specification</a>.
|
||||
* Encodes a tag list, as defined in the <a href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR Specification</a>.
|
||||
*
|
||||
* @param theTagList The tag list to encode. Must not be null.
|
||||
* @param theWriter The writer to encode to
|
||||
* @param theTagList
|
||||
* The tag list to encode. Must not be null.
|
||||
* @param theWriter
|
||||
* The writer to encode to
|
||||
*/
|
||||
void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException;
|
||||
|
||||
|
||||
<T extends IResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader);
|
||||
|
||||
Bundle parseBundle(Reader theReader);
|
||||
|
@ -70,15 +74,12 @@ public interface IParser {
|
|||
* 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 (e.g. a custom
|
||||
* type extending the default Patient class)
|
||||
* 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.
|
||||
* @return A parsed resource
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not
|
||||
* recognized or invalid for any reason
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
<T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
|
||||
|
||||
|
@ -86,15 +87,12 @@ public interface IParser {
|
|||
* 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 (e.g. a custom
|
||||
* type extending the default Patient class)
|
||||
* 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
|
||||
* @return A parsed resource
|
||||
* @throws DataFormatException
|
||||
* If the resource can not be parsed because the data is not
|
||||
* recognized or invalid for any reason
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
<T extends IResource> T parseResource(Class<T> theResourceType, String theString) throws DataFormatException;
|
||||
|
||||
|
@ -105,8 +103,7 @@ public interface IParser {
|
|||
* 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
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
|
||||
|
||||
|
@ -117,15 +114,12 @@ public interface IParser {
|
|||
* 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
|
||||
* If the resource can not be parsed because the data is not recognized or invalid for any reason
|
||||
*/
|
||||
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||
|
||||
/**
|
||||
* Parses a tag list, as defined in the <a
|
||||
* href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR
|
||||
* Specification</a>.
|
||||
* Parses a tag list, as defined in the <a href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR Specification</a>.
|
||||
*
|
||||
* @param theReader
|
||||
* A reader which will supply a tag list
|
||||
|
@ -134,9 +128,7 @@ public interface IParser {
|
|||
TagList parseTagList(Reader theReader);
|
||||
|
||||
/**
|
||||
* Parses a tag list, as defined in the <a
|
||||
* href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR
|
||||
* Specification</a>.
|
||||
* Parses a tag list, as defined in the <a href="http://hl7.org/implement/standards/fhir/http.html#tags">FHIR Specification</a>.
|
||||
*
|
||||
* @param theString
|
||||
* A string containing a tag list
|
||||
|
@ -145,20 +137,16 @@ public interface IParser {
|
|||
TagList parseTagList(String theString);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
* @return Returns an instance of <code>this</code> parser so that method
|
||||
* calls can be conveniently chained
|
||||
* @return Returns an instance of <code>this</code> parser so that method calls can be conveniently chained
|
||||
*/
|
||||
IParser setPrettyPrint(boolean thePrettyPrint);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives
|
||||
* will not be included in the encoded values.
|
||||
* If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded values.
|
||||
*/
|
||||
IParser setSuppressNarratives(boolean theSuppressNarratives);
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
||||
String theChildName) throws IOException {
|
||||
String theChildName, boolean theIsSubElementWithinResource) throws IOException {
|
||||
|
||||
switch (theChildDef.getChildType()) {
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
|
@ -278,7 +278,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (theValue instanceof ExtensionDt) {
|
||||
theWriter.write("url", ((ExtensionDt) theValue).getUrlAsString());
|
||||
}
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theValue, theWriter, childCompositeDef);
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theValue, theWriter, childCompositeDef, theIsSubElementWithinResource);
|
||||
theWriter.writeEnd();
|
||||
break;
|
||||
}
|
||||
|
@ -297,6 +297,16 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
reference = myContext.getResourceDefinition(value.getResourceType()).getName() + '/' + value.getIdPart();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(reference)) {
|
||||
if (referenceDt.getResource() != null) {
|
||||
IdDt containedId = getContainedResources().getResourceId(referenceDt.getResource());
|
||||
if (containedId != null) {
|
||||
reference = "#" + containedId.getValue();
|
||||
} else if (referenceDt.getResource().getId() != null && referenceDt.getResource().getId().hasIdPart()) {
|
||||
reference = referenceDt.getResource().getId().getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(reference)) {
|
||||
theWriter.write(XmlParser.RESREF_REFERENCE, reference);
|
||||
|
@ -313,6 +323,10 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
for (IResource next : value.getContainedResources()) {
|
||||
encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true);
|
||||
}
|
||||
for (IResource next : getContainedResources().getContainedResources()) {
|
||||
IdDt resourceId = getContainedResources().getResourceId(next);
|
||||
encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, resourceId.getValue());
|
||||
}
|
||||
theWriter.writeEnd();
|
||||
break;
|
||||
}
|
||||
|
@ -341,7 +355,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||
List<? extends BaseRuntimeChildDefinition> theChildren) throws IOException {
|
||||
List<? extends BaseRuntimeChildDefinition> theChildren, boolean theIsSubElementWithinResource) throws IOException {
|
||||
for (BaseRuntimeChildDefinition nextChild : theChildren) {
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
|
@ -351,7 +365,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theIsSubElementWithinResource);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +385,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
int valueIdx = 0;
|
||||
for (IElement nextValue : values) {
|
||||
if (nextValue == null || nextValue.isEmpty()) {
|
||||
continue;
|
||||
if (nextValue instanceof ContainedDt) {
|
||||
if (theIsSubElementWithinResource || getContainedResources().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Class<? extends IElement> type = nextValue.getClass();
|
||||
|
@ -382,6 +402,10 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
|
||||
|
||||
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && theIsSubElementWithinResource) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
||||
// Don't encode extensions
|
||||
// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
||||
|
@ -399,13 +423,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
|
||||
theEventWriter.writeStartArray(childName);
|
||||
inArray = true;
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource);
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theIsSubElementWithinResource);
|
||||
}
|
||||
currentChildName = childName;
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource);
|
||||
}
|
||||
|
||||
if (nextValue instanceof ISupportsUndeclaredExtensions && primitive) {
|
||||
|
@ -453,14 +477,24 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||
BaseRuntimeElementCompositeDefinition<?> resDef) throws IOException, DataFormatException {
|
||||
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIsSubElementWithinResource) throws IOException, DataFormatException {
|
||||
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, resDef, theResDef, theResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions());
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren());
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIsSubElementWithinResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(),theIsSubElementWithinResource);
|
||||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||
boolean theIsSubElementWithinResource) throws IOException {
|
||||
String resourceId = null;
|
||||
if (theIsSubElementWithinResource && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
resourceId = theResource.getId().getValue();
|
||||
}
|
||||
|
||||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theIsSubElementWithinResource, resourceId);
|
||||
}
|
||||
|
||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theIsSubElementWithinResource,
|
||||
String theResourceId) throws IOException {
|
||||
if (!theIsSubElementWithinResource) {
|
||||
super.containResourcesForEncoding(theResource);
|
||||
}
|
||||
|
@ -474,8 +508,8 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
theEventWriter.write("resourceType", resDef.getName());
|
||||
if (theIsSubElementWithinResource && theResource.getId() != null && isNotBlank(theResource.getId().getValue())) {
|
||||
theEventWriter.write("id", theResource.getId().getValue());
|
||||
if (theResourceId != null) {
|
||||
theEventWriter.write("id", theResourceId);
|
||||
}
|
||||
|
||||
if (theResource instanceof Binary) {
|
||||
|
@ -483,7 +517,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);
|
||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
@ -972,7 +1006,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
// theEventWriter, myValue, def, "value" +
|
||||
// WordUtils.capitalize(def.getName()));
|
||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName,false);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
@ -1003,7 +1037,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName,true);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
|
|
@ -34,8 +34,6 @@ import java.util.List;
|
|||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.FactoryConfigurationError;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
|
@ -52,6 +50,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
|
@ -153,9 +152,9 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
eventWriter.writeNamespace("at", TOMBSTONES_NS);
|
||||
eventWriter.writeAttribute("ref", nextEntry.getId().getValueAsString());
|
||||
eventWriter.writeAttribute("when", nextEntry.getDeletedAt().getValueAsString());
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false || nextEntry.getDeletedByName().isEmpty()==false) {
|
||||
if (nextEntry.getDeletedByEmail().isEmpty() == false || nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "by");
|
||||
if (nextEntry.getDeletedByName().isEmpty()==false) {
|
||||
if (nextEntry.getDeletedByName().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "name");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedByName().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
|
@ -167,7 +166,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
if (nextEntry.getDeletedComment().isEmpty()==false) {
|
||||
if (nextEntry.getDeletedComment().isEmpty() == false) {
|
||||
eventWriter.writeStartElement(TOMBSTONES_NS, "comment");
|
||||
eventWriter.writeCharacters(nextEntry.getDeletedComment().getValue());
|
||||
eventWriter.writeEndElement();
|
||||
|
@ -214,7 +213,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
eventWriter.writeEndElement(); // entry
|
||||
}
|
||||
|
||||
|
@ -225,7 +223,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
|
||||
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
|
||||
if (categories != null) {
|
||||
for (Tag next : categories) {
|
||||
eventWriter.writeStartElement("category");
|
||||
|
@ -336,15 +334,15 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
throw new DataFormatException(e1);
|
||||
}
|
||||
|
||||
// XMLEventReader streamReader;
|
||||
// try {
|
||||
// streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||
// } catch (XMLStreamException e) {
|
||||
// throw new DataFormatException(e);
|
||||
// } catch (FactoryConfigurationError e) {
|
||||
// throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
// }
|
||||
// return streamReader;
|
||||
// XMLEventReader streamReader;
|
||||
// try {
|
||||
// streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||
// } catch (XMLStreamException e) {
|
||||
// throw new DataFormatException(e);
|
||||
// } catch (FactoryConfigurationError e) {
|
||||
// throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
// }
|
||||
// return streamReader;
|
||||
}
|
||||
|
||||
private XMLStreamWriter decorateStreamWriter(XMLStreamWriter eventWriter) {
|
||||
|
@ -426,7 +424,11 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, XMLStreamWriter theEventWriter, IElement nextValue, String childName,
|
||||
BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (nextValue.isEmpty()) {
|
||||
return;
|
||||
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty()==false && theIncludedResource == false) {
|
||||
// We still want to go in..
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (childDef.getChildType()) {
|
||||
|
@ -467,6 +469,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
for (IResource next : value.getContainedResources()) {
|
||||
encodeResourceToXmlStreamWriter(next, theEventWriter, true);
|
||||
}
|
||||
for (IResource next : getContainedResources().getContainedResources()) {
|
||||
IdDt resourceId = getContainedResources().getResourceId(next);
|
||||
encodeResourceToXmlStreamWriter(next, theEventWriter, true, resourceId.getValue());
|
||||
}
|
||||
theEventWriter.writeEndElement();
|
||||
break;
|
||||
}
|
||||
|
@ -512,7 +518,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
for (IElement nextValue : values) {
|
||||
if (nextValue == null || nextValue.isEmpty()) {
|
||||
if ((nextValue == null || nextValue.isEmpty()) && !(nextValue instanceof ContainedDt)) {
|
||||
continue;
|
||||
}
|
||||
Class<? extends IElement> type = nextValue.getClass();
|
||||
|
@ -570,6 +576,17 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
// }
|
||||
// }
|
||||
|
||||
if (isBlank(reference)) {
|
||||
if (theRef.getResource() != null) {
|
||||
IdDt containedId = getContainedResources().getResourceId(theRef.getResource());
|
||||
if (containedId != null) {
|
||||
reference = "#" + containedId.getValue();
|
||||
} else if (theRef.getResource().getId() != null && theRef.getResource().getId().hasIdPart()) {
|
||||
reference = theRef.getResource().getId().getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(reference)) {
|
||||
theEventWriter.writeStartElement(RESREF_REFERENCE);
|
||||
theEventWriter.writeAttribute("value", reference);
|
||||
|
@ -582,12 +599,16 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param theIncludedResource
|
||||
* Set to true only if this resource is an "included" resource, as opposed to a "root level" resource by itself or in a bundle entry
|
||||
*
|
||||
*/
|
||||
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
String resourceId = null;
|
||||
if (theIncludedResource && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
resourceId = theResource.getId().getValue();
|
||||
}
|
||||
|
||||
encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId);
|
||||
}
|
||||
|
||||
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, String theResourceId) throws XMLStreamException {
|
||||
if (!theIncludedResource) {
|
||||
super.containResourcesForEncoding(theResource);
|
||||
}
|
||||
|
@ -600,8 +621,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeStartElement(resDef.getName());
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
if (theIncludedResource && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
theEventWriter.writeAttribute("id", theResource.getId().getValue());
|
||||
if (theResourceId != null) {
|
||||
theEventWriter.writeAttribute("id", theResourceId);
|
||||
}
|
||||
|
||||
if (theResource instanceof Binary) {
|
||||
|
|
|
@ -159,13 +159,13 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
builder.append("system", defaultString(getValue()));
|
||||
builder.append("system", defaultString(getSystem()));
|
||||
builder.append("value", getValue());
|
||||
if (myText) {
|
||||
builder.append("text", myText);
|
||||
builder.append(":text", myText);
|
||||
}
|
||||
if (getMissing() != null) {
|
||||
builder.append("missing", getMissing());
|
||||
builder.append(":missing", getMissing());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
|
|
@ -72,13 +72,15 @@ public class UnprocessableEntityException extends BaseServerResponseException {
|
|||
}
|
||||
|
||||
private static OperationOutcome toOperationOutcome(String... theMessage) {
|
||||
OperationOutcome operationOutcome = new OperationOutcome();
|
||||
OperationOutcome OperationOutcome = new OperationOutcome();
|
||||
if (theMessage != null) {
|
||||
for (String next : theMessage) {
|
||||
operationOutcome.addIssue().setDetails(next);
|
||||
OperationOutcome.addIssue().setDetails(next);
|
||||
}
|
||||
}
|
||||
return operationOutcome;
|
||||
return OperationOutcome;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -103,31 +103,109 @@ patient.getManagingOrganization().setReference("Organization/124362");]]></sourc
|
|||
<p>
|
||||
In the following example, the Organization resource has an ID set, so it will not
|
||||
be contained but will rather appear as a distinct entry in any returned
|
||||
bundles.
|
||||
bundles. Both resources are added to a bundle, which will then have
|
||||
two entries:
|
||||
</p>
|
||||
<source><![CDATA[Organization org = new Organization();
|
||||
<source><![CDATA[// Create an organization
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/65546");
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
patient.getManagingOrganization().setResource(patient);]]></source>
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
// Create a list containing both resources. In a server method, you might just
|
||||
// return this list, but here we will create a bundle to encode.
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
resources.add(org);
|
||||
resources.add(patient);
|
||||
|
||||
// Create a bundle with both
|
||||
Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base");
|
||||
|
||||
// Encode the buntdle
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
System.out.println(encoded);]]></source>
|
||||
|
||||
<p>
|
||||
This will give the following output:
|
||||
</p>
|
||||
<source><![CDATA[<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<entry>
|
||||
<title>Organization Organization/65546</title>
|
||||
<id>http://example.com/base/Organization/65546</id>
|
||||
<published>2014-10-14T09:22:54-04:00</published>
|
||||
<link rel="self" href="http://example.com/base/Organization/65546"/>
|
||||
<content type="text/xml">
|
||||
<Organization xmlns="http://hl7.org/fhir">
|
||||
<name value="Contained Test Organization"/>
|
||||
</Organization>
|
||||
</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>Patient Patient/1333</title>
|
||||
<id>http://example.com/base/Patient/1333</id>
|
||||
<published>2014-10-14T09:22:54-04:00</published>
|
||||
<link rel="self" href="http://example.com/base/Patient/1333"/>
|
||||
<content type="text/xml">
|
||||
<Patient xmlns="http://hl7.org/fhir">
|
||||
<identifier>
|
||||
<system value="urn:mrns"/>
|
||||
<value value="253345"/>
|
||||
</identifier>
|
||||
<managingOrganization>
|
||||
<reference value="Organization/65546"/>
|
||||
</managingOrganization>
|
||||
</Patient>
|
||||
</content>
|
||||
</entry>
|
||||
</feed>]]></source>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Contained Resources">
|
||||
|
||||
<p>
|
||||
On the other hand, if the linked resource
|
||||
does not have an ID set, the linked resource will
|
||||
be included in the returned bundle as a "contained" resource. In this
|
||||
case, HAPI itself will define a local reference ID (e.g. "#001").
|
||||
case, HAPI itself will define a local reference ID (e.g. "#1").
|
||||
</p>
|
||||
<source><![CDATA[Organization org = new Organization();
|
||||
// org.setId("Organization/65546");
|
||||
org.getName().setValue("Normal (not contained) Test Organization");
|
||||
<source><![CDATA[// Create an organization, note that the organization does not have an ID
|
||||
Organization org = new Organization();
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
patient.getManagingOrganization().setResource(patient);]]></source>
|
||||
|
||||
// Put the organization as a reference in the patient resource
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||
System.out.println(encoded);]]></source>
|
||||
|
||||
<p>
|
||||
This will give the following output:
|
||||
</p>
|
||||
<source><![CDATA[<Patient xmlns="http://hl7.org/fhir">
|
||||
<contained>
|
||||
<Organization xmlns="http://hl7.org/fhir" id="1">
|
||||
<name value="Contained Test Organization"/>
|
||||
</Organization>
|
||||
</contained>
|
||||
<identifier>
|
||||
<system value="urn:mrns"/>
|
||||
<value value="253345"/>
|
||||
</identifier>
|
||||
<managingOrganization>
|
||||
<reference value="#1"/>
|
||||
</managingOrganization>
|
||||
</Patient>]]></source>
|
||||
|
||||
</subsection>
|
||||
|
||||
|
|
|
@ -133,11 +133,11 @@ public class ContainedResourceEncodingTest {
|
|||
final String expectedCompXml = parser.encodeResourceToString(this.comp);
|
||||
logger.debug("[xmlEncoding] first encoding: {}", expectedCompXml);
|
||||
|
||||
assertEquals(3, this.comp.getContained().getContainedResources().size());
|
||||
assertEquals(0, this.comp.getContained().getContainedResources().size());
|
||||
|
||||
final String actualCompXml = parser.encodeResourceToString(this.comp);
|
||||
|
||||
assertEquals(3, this.comp.getContained().getContainedResources().size());
|
||||
assertEquals(0, this.comp.getContained().getContainedResources().size());
|
||||
|
||||
// second encoding - xml could not be parsed back to compositon - i.e.: patient content 4 times! should be the same
|
||||
// as after first encoding!
|
||||
|
@ -145,7 +145,7 @@ public class ContainedResourceEncodingTest {
|
|||
|
||||
final String thirdCompXml = parser.encodeResourceToString(this.comp);
|
||||
|
||||
assertEquals(3, this.comp.getContained().getContainedResources().size());
|
||||
assertEquals(0, this.comp.getContained().getContainedResources().size());
|
||||
|
||||
// third encoding - xml could not be parsed back to compositon i.e.: patient content 4 times! should be the same as
|
||||
// afterfirst encoding!
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.io.StringReader;
|
|||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.json.JSON;
|
||||
|
@ -88,6 +89,30 @@ public class JsonParserTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeNonContained() {
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/65546");
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
Bundle b = Bundle.withResources(Collections.singletonList((IResource)patient), ourCtx, "http://foo");
|
||||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, not(containsString("contained")));
|
||||
assertThat(encoded, containsString("\"reference\":\"Organization/65546\""));
|
||||
|
||||
encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, not(containsString("contained")));
|
||||
assertThat(encoded, containsString("\"reference\":\"Organization/65546\""));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeIds() {
|
||||
Patient pt =new Patient();
|
||||
|
@ -437,6 +462,38 @@ public class JsonParserTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeContained() {
|
||||
// Create an organization
|
||||
Organization org = new Organization();
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
// Create a bundle with just the patient resource
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
resources.add(patient);
|
||||
Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base");
|
||||
|
||||
// Encode the buntdle
|
||||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\"")));
|
||||
assertThat(encoded, containsString("reference\":\"#1\""));
|
||||
|
||||
encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\"")));
|
||||
assertThat(encoded, containsString("reference\":\"#1\""));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeContainedResources() throws IOException {
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.io.StringReader;
|
|||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -78,6 +79,77 @@ public class XmlParserTest {
|
|||
System.setProperty("file.encoding", "ISO-8859-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeNonContained() {
|
||||
// Create an organization
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/65546");
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
// Create a list containing both resources. In a server method, you might just
|
||||
// return this list, but here we will create a bundle to encode.
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
resources.add(org);
|
||||
resources.add(patient);
|
||||
|
||||
// Create a bundle with both
|
||||
Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base");
|
||||
|
||||
// Encode the buntdle
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, not(containsString("<contained>")));
|
||||
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
|
||||
|
||||
encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, not(containsString("<contained>")));
|
||||
assertThat(encoded, containsString("<reference value=\"Organization/65546\"/>"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeContained() {
|
||||
// Create an organization, note that the organization does not have an ID
|
||||
Organization org = new Organization();
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/1333");
|
||||
patient.addIdentifier("urn:mrns", "253345");
|
||||
|
||||
// Put the organization as a reference in the patient resource
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("<contained>"));
|
||||
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
|
||||
|
||||
// Create a bundle with just the patient resource
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
resources.add(patient);
|
||||
Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base");
|
||||
|
||||
// Encode the buntdle
|
||||
encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("<contained>"));
|
||||
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thanks to Alexander Kley!
|
||||
*/
|
||||
|
@ -85,9 +157,9 @@ public class XmlParserTest {
|
|||
public void testParseContainedBinaryResource() {
|
||||
byte[] bin = new byte[] {0,1,2,3,4};
|
||||
final Binary binary = new Binary("PatientConsent", bin);
|
||||
binary.setId(UUID.randomUUID().toString());
|
||||
// binary.setId(UUID.randomUUID().toString());
|
||||
DocumentManifest manifest = new DocumentManifest();
|
||||
manifest.setId(UUID.randomUUID().toString());
|
||||
// manifest.setId(UUID.randomUUID().toString());
|
||||
manifest.setType(new CodeableConceptDt("mySystem", "PatientDocument"));
|
||||
manifest.setMasterIdentifier("mySystem", UUID.randomUUID().toString());
|
||||
manifest.addContent().setResource(binary);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -25,6 +26,8 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.net.UrlEscapers;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -42,6 +45,7 @@ import ca.uhn.fhir.rest.param.ReferenceParam;
|
|||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
|
||||
/**
|
||||
|
@ -121,6 +125,23 @@ public class SearchTest {
|
|||
assertEquals("bbb", p.getIdentifier().get(1).getValue().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithTokenParameter() throws Exception {
|
||||
String token = UrlEscapers.urlFragmentEscaper().asFunction().apply("http://www.dmix.gov/vista/2957|301");
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?tokenParam="+token);
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
|
||||
Patient p = bundle.getResources(Patient.class).get(0);
|
||||
assertEquals("http://www.dmix.gov/vista/2957", p.getNameFirstRep().getFamilyAsSingleString());
|
||||
assertEquals("301", p.getNameFirstRep().getGivenAsSingleString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByPost() throws Exception {
|
||||
HttpPost filePost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search");
|
||||
|
@ -325,6 +346,18 @@ public class SearchTest {
|
|||
}
|
||||
|
||||
|
||||
@Search()
|
||||
public List<Patient> findPatientWithToken(@RequiredParam(name = "tokenParam") TokenParam theParam) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("1");
|
||||
patient.addName().addFamily(theParam.getSystem()).addGiven(theParam.getValue());
|
||||
retVal.add(patient);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Search(queryName = "findWithLinks")
|
||||
public List<Patient> findWithLinks() {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
|
Loading…
Reference in New Issue