Add model visitor, and allow bundles to have categories (as allowed in the spec)

This commit is contained in:
jamesagnew 2014-08-19 07:48:06 -04:00
parent fd41bafa82
commit 598eec53ed
13 changed files with 706 additions and 554 deletions

View File

@ -17,22 +17,19 @@ import ca.uhn.fhir.rest.method.SearchStyleEnum;
public class GenericClientExample {
@SuppressWarnings("unused")
public static void simpleExample() {
// START SNIPPET: simple
FhirContext ctx = new FhirContext();
String serverBase = "http://fhir.healthintersections.com.au/open";
String serverBase = "http://fhirtest.uhn.ca/base";
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
// Read a patient
Patient patient = client.read(Patient.class, "1");
// Perform a search
Bundle results = client.search()
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value("duck"))
.execute();
// Change the patient and update it to the server
patient.getNameFirstRep().getFamilyFirstRep().setValue("Jones");
client.update("1", patient);
// Return the version history for that patient
Bundle versions = client.history(Patient.class, "1",null,null);
System.out.println("Found " + results.size() + " patients named 'duck'");
// END SNIPPET: simple
}
@ -177,7 +174,7 @@ List<IResource> response = client.transaction()
}
public static void main(String[] args) {
// nothing
simpleExample();
}
}

View File

@ -87,6 +87,10 @@
Transaction method in server can now have parameter type Bundle instead of
List&lt;IResource&gt;
</action>
<action type="add">
HAPI parsers now use field access to get/set values instead of method accessors and mutators.
This should give a small performance boost.
</action>
</release>
<release version="0.5" date="2014-Jul-30">
<action type="add">

View File

@ -44,11 +44,6 @@ public class Bundle extends BaseBundle /* implements IElement */{
private volatile transient Map<IdDt, IResource> myIdToEntries;
//@formatter:off
/* ****************************************************
* NB: add any new fields to the isEmpty() method!!!
*****************************************************/
//@formatter:on
private List<BundleEntry> myEntries;
private StringDt myBundleId;
private StringDt myLinkBase;
@ -61,6 +56,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
private StringDt myTitle;
private IntegerDt myTotalResults;
private InstantDt myUpdated;
private TagList myCategories;
/**
* Returns true if this bundle contains zero entries
@ -70,6 +66,16 @@ public class Bundle extends BaseBundle /* implements IElement */{
return getEntries().isEmpty();
}
public Tag addCategory() {
Tag retVal = new Tag();
getCategories().add(retVal);
return retVal;
}
public void addCategory(Tag theTag) {
getCategories().add(theTag);
}
/**
* Adds and returns a new bundle entry
*/
@ -82,12 +88,15 @@ public class Bundle extends BaseBundle /* implements IElement */{
/**
* Retrieves a resource from a bundle given its logical ID.
* <p>
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
* <code>http://bar/Patient/123</code>. Also, this method is intended to be used for bundles which have already been populated. It will cache its results for fast performance, but that means that
* modifications to the bundle after this method is called may not be accurately reflected.
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of
* <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
* <code>http://bar/Patient/123</code>. Also, this method is intended to be used for bundles which have already been
* populated. It will cache its results for fast performance, but that means that modifications to the bundle after
* this method is called may not be accurately reflected.
* </p>
*
* @param theId The resource ID
* @param theId
* The resource ID
* @return Returns the resource with the given ID, or <code>null</code> if none is found
*/
public IResource getResourceById(IdDt theId) {
@ -104,31 +113,43 @@ public class Bundle extends BaseBundle /* implements IElement */{
return map.get(theId.toUnqualified());
}
// public static void main(String[] args) {
//
// FhirContext ctx = new FhirContext();
// String txt = "<Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://fhir.connectinggta.ca/Profile/organization#providerIdPool\">\n" +
// " <valueUri value=\"urn:oid:2.16.840.1.113883.3.239.23.21.1\"/>\n" +
// " </extension>\n" +
// " <text>\n" +
// " <status value=\"generated\"/>\n" +
// " <div xmlns=\"http://www.w3.org/1999/xhtml\"/>\n" +
// " </text>\n" +
// " <identifier>\n" +
// " <use value=\"official\"/>\n" +
// " <label value=\"HSP 2.16.840.1.113883.3.239.23.21\"/>\n" +
// " <system value=\"urn:cgta:hsp_ids\"/>\n" +
// " <value value=\"urn:oid:2.16.840.1.113883.3.239.23.21\"/>\n" +
// " </identifier>\n" +
// " <name value=\"火星第五人民医院\"/>\n" +
// "</Organization>";
//
// IGenericClient c = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/base");
// c.registerInterceptor(new LoggingInterceptor(true));
// c.update().resource(txt).withId("1665").execute();
// }
//
// public static void main(String[] args) {
//
// FhirContext ctx = new FhirContext();
// String txt = "<Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://fhir.connectinggta.ca/Profile/organization#providerIdPool\">\n" +
// " <valueUri value=\"urn:oid:2.16.840.1.113883.3.239.23.21.1\"/>\n" +
// " </extension>\n" +
// " <text>\n" +
// " <status value=\"generated\"/>\n" +
// " <div xmlns=\"http://www.w3.org/1999/xhtml\"/>\n" +
// " </text>\n" +
// " <identifier>\n" +
// " <use value=\"official\"/>\n" +
// " <label value=\"HSP 2.16.840.1.113883.3.239.23.21\"/>\n" +
// " <system value=\"urn:cgta:hsp_ids\"/>\n" +
// " <value value=\"urn:oid:2.16.840.1.113883.3.239.23.21\"/>\n" +
// " </identifier>\n" +
// " <name value=\"火星第五人民医院\"/>\n" +
// "</Organization>";
//
// IGenericClient c = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/base");
// c.registerInterceptor(new LoggingInterceptor(true));
// c.update().resource(txt).withId("1665").execute();
// }
//
public TagList getCategories() {
if (myCategories == null) {
myCategories = new TagList();
}
return myCategories;
}
public void setCategories(TagList theCategories) {
myCategories = theCategories;
}
public List<BundleEntry> getEntries() {
if (myEntries == null) {
myEntries = new ArrayList<BundleEntry>();
@ -264,7 +285,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
*
* @param theResource
* The resource to add
* @return Returns the newly created bundle entry that was added to the bundle
* @return Returns the newly created bundle entry that was added to the bundle
*/
public BundleEntry addResource(IResource theResource, FhirContext theContext, String theServerBase) {
BundleEntry entry = addEntry();
@ -278,7 +299,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
} else {
entry.getTitle().setValue(def.getName() + " " + StringUtils.defaultString(theResource.getId().getValue(), "(no ID)"));
}
if (theResource.getId() != null && StringUtils.isNotBlank(theResource.getId().getValue())) {
StringBuilder b = new StringBuilder();
@ -310,9 +331,9 @@ public class Bundle extends BaseBundle /* implements IElement */{
String qualifiedId = b.toString();
entry.getLinkSelf().setValue(qualifiedId);
// String resourceType = theContext.getResourceDefinition(theResource).getName();
// String resourceType = theContext.getResourceDefinition(theResource).getName();
String linkSearch = ResourceMetadataKeyEnum.LINK_SEARCH.get(theResource);
if (isNotBlank(linkSearch)) {
if (!UrlUtil.isAbsolute(linkSearch)) {
@ -320,7 +341,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
}
entry.getLinkSearch().setValue(linkSearch);
}
String linkAlternate = ResourceMetadataKeyEnum.LINK_ALTERNATE.get(theResource);
if (isNotBlank(linkAlternate)) {
if (!UrlUtil.isAbsolute(linkAlternate)) {
@ -328,7 +349,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
}
entry.getLinkAlternate().setValue(linkSearch);
}
}
InstantDt published = ResourceMetadataKeyEnum.PUBLISHED.get(theResource);

View File

@ -166,6 +166,8 @@ public class JsonParser extends BaseParser implements IParser {
if (linkStarted) {
eventWriter.writeEnd();
}
writeCategories(eventWriter, theBundle.getCategories());
writeOptionalTagWithTextNode(eventWriter, "totalResults", theBundle.getTotalResults());
@ -193,17 +195,7 @@ public class JsonParser extends BaseParser implements IParser {
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
if (nextEntry.getCategories() != null && nextEntry.getCategories().size() > 0) {
eventWriter.writeStartArray("category");
for (Tag next : nextEntry.getCategories()) {
eventWriter.writeStartObject();
eventWriter.write("term", defaultString(next.getTerm()));
eventWriter.write("label", defaultString(next.getLabel()));
eventWriter.write("scheme", defaultString(next.getScheme()));
eventWriter.writeEnd();
}
eventWriter.writeEnd();
}
writeCategories(eventWriter, nextEntry.getCategories());
writeAuthor(nextEntry, eventWriter);
@ -221,6 +213,20 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.flush();
}
private void writeCategories(JsonGenerator eventWriter, TagList categories) {
if (categories != null && categories.size() > 0) {
eventWriter.writeStartArray("category");
for (Tag next : categories) {
eventWriter.writeStartObject();
eventWriter.write("term", defaultString(next.getTerm()));
eventWriter.write("label", defaultString(next.getLabel()));
eventWriter.write("scheme", defaultString(next.getScheme()));
eventWriter.writeEnd();
}
eventWriter.writeEnd();
}
}
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
String theChildName) throws IOException {

View File

@ -20,8 +20,7 @@ package ca.uhn.fhir.parser;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.util.ArrayList;
import java.util.HashMap;
@ -67,6 +66,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.IModelVisitor;
class ParserState<T> {
@ -628,6 +628,8 @@ class ParserState<T> {
push(new AtomPrimitiveState(myInstance.getUpdated()));
} else if ("author".equals(theLocalPart)) {
push(new AtomAuthorState(myInstance));
} else if ("category".equals(theLocalPart)) {
push(new AtomCategoryState(myInstance.getCategories().addTag()));
} else if ("deleted-entry".equals(theLocalPart) && verifyNamespace(XmlParser.TOMBSTONES_NS, theNamespaceURI)) {
push(new AtomDeletedEntryState(myInstance, myResourceType));
} else {
@ -908,7 +910,7 @@ class ParserState<T> {
public void attributeValue(String theName, String theValue) throws DataFormatException {
if ("id".equals(theName)) {
if (myInstance instanceof IIdentifiableElement) {
((IIdentifiableElement) myInstance).setId(new IdDt(theValue));
((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
} else if (myInstance instanceof IResource) {
((IResource) myInstance).setId(new IdDt(theValue));
}
@ -1255,20 +1257,32 @@ class ParserState<T> {
myObject = (T) myInstance;
}
for (ResourceReferenceDt nextRef : myResourceReferences) {
String ref = nextRef.getReference().getValue();
if (isNotBlank(ref)) {
if (ref.startsWith("#")) {
IResource target = myContainedResources.get(ref.substring(1));
if (target != null) {
nextRef.setResource(target);
} else {
ourLog.warn("Resource contains unknown local ref: " + ref);
myContext.newTerser().visit(myInstance, new IModelVisitor() {
@Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
acceptElement(theNextExt.getValue(), null, null);
}
@Override
public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
if (theElement instanceof ResourceReferenceDt) {
ResourceReferenceDt nextRef = (ResourceReferenceDt)theElement;
String ref = nextRef.getReference().getValue();
if (isNotBlank(ref)) {
if (ref.startsWith("#")) {
IResource target = myContainedResources.get(ref.substring(1));
if (target != null) {
nextRef.setResource(target);
} else {
ourLog.warn("Resource contains unknown local ref: " + ref);
}
}
}
}
}
}
});
}
}

View File

@ -144,6 +144,8 @@ public class XmlParser extends BaseParser implements IParser {
eventWriter.writeEndElement();
}
writeCategories(eventWriter, theBundle.getCategories());
for (BundleEntry nextEntry : theBundle.getEntries()) {
boolean deleted = false;
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
@ -182,15 +184,7 @@ public class XmlParser extends BaseParser implements IParser {
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
if (nextEntry.getCategories() != null) {
for (Tag next : nextEntry.getCategories()) {
eventWriter.writeStartElement("category");
eventWriter.writeAttribute("term", defaultString(next.getTerm()));
eventWriter.writeAttribute("label", defaultString(next.getLabel()));
eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
eventWriter.writeEndElement();
}
}
writeCategories(eventWriter, nextEntry.getCategories());
if (!nextEntry.getLinkSelf().isEmpty()) {
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
@ -224,6 +218,18 @@ public class XmlParser extends BaseParser implements IParser {
}
}
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
if (categories != null) {
for (Tag next : categories) {
eventWriter.writeStartElement("category");
eventWriter.writeAttribute("term", defaultString(next.getTerm()));
eventWriter.writeAttribute("label", defaultString(next.getLabel()));
eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
eventWriter.writeEndElement();
}
}
}
@Override
public String encodeResourceToString(IResource theResource) throws DataFormatException {
if (theResource == null) {

View File

@ -108,30 +108,64 @@ public class FhirTerser {
}
/**
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b>
* and are either of the exact type specified, or are a subclass of that type.
* Visit all elements in a given resource
*
* @param theResource The resource to visit
* @param theVisitor The visitor
*/
public void visit(IResource theResource, IModelVisitor theVisitor) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, theVisitor);
}
/**
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are
* either of the exact type specified, or are a subclass of that type.
* <p>
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within
* the message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained resources.
* </p>
* @param theResourceT The resource instance to search. Must not be null.
* @param theType The type to search for. Must not be null.
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within the
* message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained
* resources.
* </p>
*
* @param theResourceT
* The resource instance to search. Must not be null.
* @param theType
* The type to search for. Must not be null.
* @return
*/
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, Class<T> theType) {
ArrayList<T> retVal = new ArrayList<T>();
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, final Class<T> theType) {
final ArrayList<T> retVal = new ArrayList<T>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
getAllChildElementsOfType(theResource, def, theType, retVal);
visit(theResource, null, def, new IModelVisitor() {
@SuppressWarnings("unchecked")
@Override
public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
if (theElement.isEmpty()) {
return;
}
if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
retVal.add((T) theElement);
}
}
@SuppressWarnings("unchecked")
@Override
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
if (theType.isAssignableFrom(theNextExt.getClass())) {
retVal.add((T) theNextExt);
}
if (theNextExt.getValue() != null && theType.isAssignableFrom(theNextExt.getValue().getClass())) {
retVal.add((T) theNextExt.getValue());
}
}
});
return retVal;
}
private <T extends IElement> void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition<?> theDefinition, Class<T> theType, ArrayList<T> theList) {
if (theElement.isEmpty()) {
return;
}
addIfCorrectType(theElement, theType, theList);
addUndeclaredExtensions(theElement, theType, theList);
private <T extends IElement> void visit(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
theCallback.acceptElement(theElement, theChildDefinition, theDefinition);
addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
switch (theDefinition.getChildType()) {
case PRIMITIVE_XHTML:
@ -171,7 +205,7 @@ public class FhirTerser {
}
throw new DataFormatException(b.toString());
}
getAllChildElementsOfType(nextValue, childElementDef, theType, theList);
visit(nextValue, nextChild, childElementDef, theCallback);
}
}
}
@ -181,7 +215,7 @@ public class FhirTerser {
ContainedDt value = (ContainedDt) theElement;
for (IResource next : value.getContainedResources()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next);
getAllChildElementsOfType(next, def, theType, theList);
visit(next, null, def, theCallback);
}
break;
}
@ -192,22 +226,14 @@ public class FhirTerser {
}
}
private <T extends IElement> void addUndeclaredExtensions(IElement theElement, Class<T> theType, ArrayList<T> theList) {
private <T extends IElement> void addUndeclaredExtensions(IElement theElement, BaseRuntimeElementDefinition<?> theDefinition, BaseRuntimeChildDefinition theChildDefinition, IModelVisitor theCallback) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions elem = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : elem.getUndeclaredExtensions()) {
addIfCorrectType(nextExt, theType, theList);
addIfCorrectType(nextExt.getValue(), theType, theList);
addUndeclaredExtensions(nextExt, theType, theList);
ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
theCallback.acceptUndeclaredExtension(containingElement, theChildDefinition, theDefinition, nextExt);
addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
}
}
}
@SuppressWarnings("unchecked")
private <T extends IElement> void addIfCorrectType(IElement theElement, Class<T> theType, ArrayList<T> theList) {
if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
theList.add((T) theElement);
}
}
}

View File

@ -0,0 +1,33 @@
package ca.uhn.fhir.util;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
/**
* @see FhirTerser#visit(ca.uhn.fhir.model.api.IResource, IModelVisitor)
*/
public interface IModelVisitor {
/**
*
* @param theElement
* @param theChildDefinition May be null if this is a root element
* @param theDefinition
*/
void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition);
/**
*
* @param theContainingElement
* @param theChildDefinition May be null if this is a root element
* @param theDefinition
* @param theNextExt
*/
void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt);
}

View File

@ -27,8 +27,9 @@
There are two types of clients provided by HAPI: Generic and Annotation-driven.
The generic client (introduced in HAPI-FHIR 0.3) is much simpler to create
and generally provides the faster way to get started. The annotation-driven
client is more powerful and can rely on code generation to give better
compile-time checking.
client can rely on code generation and static binding to specific operations to
give better compile-time checking against servers with a specific set of capabilities
exposed.
</p>
</section>
@ -75,21 +76,13 @@
such as <code>encodedJson()</code> or <code>encodedXml()</code>.
</p>
</subsection>
<subsection name="Type - Create">
<p>
The following example shows how to perform a create
operation using the generic client:
</p>
<macro name="snippet">
<param name="id" value="create" />
<param name="file"
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Type - Search/Query">
<p>
Searching for resources is probably the most common initial scenario for
client applications, so we'll start the demonstration there.
</p>
<p>
The following example shows how to query using the generic client:
</p>
@ -173,6 +166,18 @@
</subsection>
<subsection name="Type - Create">
<p>
The following example shows how to perform a create
operation using the generic client:
</p>
<macro name="snippet">
<param name="id" value="create" />
<param name="file"
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Instance - Delete">
<p>
The following example shows how to perform a delete

View File

@ -29,7 +29,10 @@ public class ModelExtensionTest {
MyPatient parsed = ourCtx.newXmlParser().parseResource(MyPatient.class, str);
assertEquals("foo", parsed.getIdentifierFirstRep().getSystem().getValueAsString());
// assertEquals(MyOrganization.class, parsed.getManagingOrganization().getResource().getClass());
// MyOrganization parsedOrg = (MyOrganization) parsed.getManagingOrganization().getResource();
// assertEquals("arg0", parsedOrg.getName().getValue());
}
}

View File

@ -363,6 +363,29 @@ public class JsonParserTest {
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
b.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = new FhirContext().newJsonParser().setPrettyPrint(false).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("\"category\":[{\"term\":\"term\",\"label\":\"label\",\"scheme\":\"scheme\"}]"));
b = new FhirContext().newJsonParser().parseBundle(val);
assertEquals(1,b.getEntries().size());
assertEquals(1,b.getCategories().size());
assertEquals("term", b.getCategories().get(0).getTerm());
assertEquals("label", b.getCategories().get(0).getLabel());
assertEquals("scheme", b.getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundleEntryCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
@ -382,7 +405,6 @@ public class JsonParserTest {
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeContainedResources() throws IOException {
@ -671,6 +693,11 @@ public class JsonParserTest {
IParser p = ourCtx.newJsonParser();
Bundle bundle = p.parseBundle(msg);
assertEquals(1, bundle.getCategories().size());
assertEquals("http://scheme", bundle.getCategories().get(0).getScheme());
assertEquals("http://term", bundle.getCategories().get(0).getTerm());
assertEquals("label", bundle.getCategories().get(0).getLabel());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
ourLog.info(encoded);

View File

@ -63,16 +63,19 @@ import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
public class XmlParserTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
@Test
public void testParseLanguage() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\"><language value=\"zh-CN\"/><text><status value=\"generated\"/><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> 海生 <b>王 </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>URNo</td></tr><tr><td>Address</td><td><span>99 Houston Road </span><br/><span>BENTLEIGH </span><span>Victoria </span></td></tr><tr><td>Date of birth</td><td><span>01 January 1997</span></td></tr></tbody></table></div></text><identifier><use value=\"usual\"/><label value=\"URNo\"/><value value=\"89532\"/></identifier><name><text value=\"王海生\"/><family value=\"\"/><given value=\"海生\"/></name><telecom><system value=\"phone\"/><value value=\"9899 9878\"/><use value=\"home\"/></telecom><telecom><system value=\"email\"/><value value=\"zimmerman@datacorp.com.au\"/><use value=\"home\"/></telecom><gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\"/><code value=\"M\"/><display value=\"Male\"/></coding><text value=\"Male\"/></gender><birthDate value=\"1997-01-01\"/><address><use value=\"home\"/><text value=\"99 Houston Road, BENTLEIGH, 3204\"/><line value=\"99 Houston Road\"/><city value=\"BENTLEIGH\"/><state value=\"Victoria\"/><zip value=\"3204\"/><period><start value=\"2006-06-16\"/></period></address><active value=\"true\"/></Patient>";
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
public void testEncodeBinaryResource() {
Binary patient = new Binary();
patient.setContentType("foo");
patient.setContent(new byte[] {1,2,3,4});
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
assertEquals("zh-CN", pt.getLanguage().getValue());
}
@Test
@ -88,284 +91,11 @@ public class XmlParserTest {
}
@Test
public void testNestedContainedResources() {
Observation A = new Observation();
A.getName().setText("A");
Observation B = new Observation();
B.getName().setText("B");
A.addRelated().setTarget(new ResourceReferenceDt(B));
Observation C = new Observation();
C.getName().setText("C");
B.addRelated().setTarget(new ResourceReferenceDt(C));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A);
ourLog.info(str);
assertThat(str, stringContainsInOrder(Arrays.asList("<text value=\"B\"/>", "<text value=\"C\"/>", "<text value=\"A\"/>")));
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>")));
// Only one (outer) contained block
int idx0 = str.indexOf("<contained>");
int idx1 = str.indexOf("<contained>",idx0+1);
assertNotEquals(-1, idx0);
assertEquals(-1, idx1);
Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
assertEquals("A",obs.getName().getText().getValue());
Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource();
assertEquals("B",obsB.getName().getText().getValue());
Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource();
assertEquals("C",obsC.getName().getText().getValue());
}
@Test
public void testParseQuery() {
String msg = "<Query xmlns=\"http://hl7.org/fhir\">\n" +
" <text>\n" +
" <status value=\"generated\"/>\n" +
" <div xmlns=\"http://www.w3.org/1999/xhtml\">[Put rendering here]</div>\n" +
" </text>\n" +
"\n" +
" <!-- this is an extermely simple query - a request to execute the query 'example' on the\n" +
" responder -->\n" +
" <identifier value=\"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\"/>\n" +
" <parameter url=\"http://hl7.org/fhir/query#_query\">\n" +
" <valueString value=\"example\"/>\n" +
" </parameter>\n" +
"</Query>";
Query query = ourCtx.newXmlParser().parseResource(Query.class, msg);
assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString());
assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString());
assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString());
}
@Test
public void testEncodeQuery() {
Query q = new Query();
ExtensionDt parameter = q.addParameter();
parameter.setUrl("http://foo").setValue(new StringDt("bar"));
String val = ourCtx.newXmlParser().encodeResourceToString(q);
ourLog.info(val);
assertEquals("<Query xmlns=\"http://hl7.org/fhir\"><parameter url=\"http://foo\"><valueString value=\"bar\"/></parameter></Query>", val);
}
@Test
public void testEncodeBinaryResource() {
Binary patient = new Binary();
patient.setContentType("foo");
patient.setContent(new byte[] {1,2,3,4});
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
}
@Test
public void testParseBinaryResource() {
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
assertEquals("foo", val.getContentType());
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
}
@Test
public void testTagList() {
//@formatter:off
String tagListStr = "<taglist xmlns=\"http://hl7.org/fhir\"> \n" +
" <category term=\"term0\" label=\"label0\" scheme=\"scheme0\" /> \n" +
" <category term=\"term1\" label=\"label1\" scheme=\"\" /> \n" +
" <category term=\"term2\" label=\"label2\" /> \n" +
"</taglist>";
//@formatter:on
TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr);
assertEquals(3, tagList.size());
assertEquals("term0", tagList.get(0).getTerm());
assertEquals("label0", tagList.get(0).getLabel());
assertEquals("scheme0", tagList.get(0).getScheme());
assertEquals("term1", tagList.get(1).getTerm());
assertEquals("label1", tagList.get(1).getLabel());
assertEquals(null, tagList.get(1).getScheme());
assertEquals("term2", tagList.get(2).getTerm());
assertEquals("label2", tagList.get(2).getLabel());
assertEquals(null, tagList.get(2).getScheme());
/*
* Encode
*/
//@formatter:off
String expected = "<taglist xmlns=\"http://hl7.org/fhir\">" +
"<category term=\"term0\" label=\"label0\" scheme=\"scheme0\"/>" +
"<category term=\"term1\" label=\"label1\"/>" +
"<category term=\"term2\" label=\"label2\"/>" +
"</taglist>";
//@formatter:on
String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList);
assertEquals(expected,encoded);
}
@Test
public void testTotalResultsUsingOldNamespace() {
//@formatter:off
String bundle = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title>Search results for Patient</title>\n" +
" <id>urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8</id>\n" +
" <totalResults xmlns=\"http://purl.org/atompub/tombstones/1.0\">15</totalResults>\n" +
" <updated>2014-05-04T13:19:47.027-04:00</updated>\n" +
" <author>\n" +
" <name>AEGIS Wildfhir Server</name>\n" +
" </author>" +
"</feed>";
//@formatter:off
Bundle bundleR = ourCtx.newXmlParser().parseBundle(bundle);
assertEquals(15, bundleR.getTotalResults().getValue().intValue());
}
@Test
public void testEncodeExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
Patient actual = parser.parseResource(Patient.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, ext.size());
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
ResourceReferenceDt ref = actual.getFoo();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeUndeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeBundleResultCount() {
Bundle b = new Bundle();
b.getTotalResults().setValue(123);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">123</os:totalResults>"));
}
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
e.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<category term=\"term\" label=\"label\" scheme=\"scheme\"/>"));
b = ourCtx.newXmlParser().parseBundle(val);
assertEquals(1, b.getEntries().size());
assertEquals(1, b.getEntries().get(0).getCategories().size());
assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm());
assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel());
assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundle() throws InterruptedException {
Bundle b= new Bundle();
b.getCategories().addTag("http://hl7.org/fhir/tag", "http://hl7.org/fhir/tag/message", "Message");
InstantDt pub = InstantDt.withCurrentTime();
b.setPublished(pub);
Thread.sleep(2);
@ -393,6 +123,7 @@ public class XmlParserTest {
List<String> strings = new ArrayList<String>();
strings.addAll(Arrays.asList("<published>", pub.getValueAsString(), "</published>"));
strings.add("<category term=\"http://hl7.org/fhir/tag/message\" label=\"Message\" scheme=\"http://hl7.org/fhir/tag\"/>");
strings.addAll(Arrays.asList("<entry>", "<id>1</id>", "</entry>"));
strings.addAll(Arrays.asList("<entry>", "<id>2</id>", "<link rel=\"alternate\" href=\"http://foo/bar\"/>", "<link rel=\"search\" href=\"http://foo/bar/search\"/>","</entry>"));
strings.addAll(Arrays.asList("<at:deleted-entry", "ref=\"Patient/3", "/>"));
@ -402,6 +133,44 @@ public class XmlParserTest {
}
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
e.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<category term=\"term\" label=\"label\" scheme=\"scheme\"/>"));
b = ourCtx.newXmlParser().parseBundle(val);
assertEquals(1, b.getEntries().size());
assertEquals(1, b.getEntries().get(0).getCategories().size());
assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm());
assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel());
assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundleResultCount() {
Bundle b = new Bundle();
b.getTotalResults().setValue(123);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">123</os:totalResults>"));
}
@Test
public void testEncodeContainedAndIncludedResources() {
@ -421,8 +190,6 @@ public class XmlParserTest {
}
@Test
public void testEncodeContainedResources() {
@ -446,6 +213,66 @@ public class XmlParserTest {
}
@Test
public void testEncodeDeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
ResourceReferenceDt ref = actual.getFoo();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
Patient actual = parser.parseResource(Patient.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, ext.size());
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeInvalidChildGoodException() {
Observation obs = new Observation();
@ -502,7 +329,20 @@ public class XmlParserTest {
}
@Test
public void testEncodeQuery() {
Query q = new Query();
ExtensionDt parameter = q.addParameter();
parameter.setUrl("http://foo").setValue(new StringDt("bar"));
String val = ourCtx.newXmlParser().encodeResourceToString(q);
ourLog.info(val);
assertEquals("<Query xmlns=\"http://hl7.org/fhir\"><parameter url=\"http://foo\"><valueString value=\"bar\"/></parameter></Query>", val);
}
@Test
public void testEncodeResourceRef() throws DataFormatException {
@ -525,6 +365,76 @@ public class XmlParserTest {
}
@Test
public void testEncodeUndeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testExtensionOnComposite() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
HumanNameDt given = name.addGiven("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
given.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension><family value=\"Shmoe\"/><given value=\"Joe\"/></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
}
@Test
public void testExtensionOnPrimitive() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
StringDt family = name.addFamily();
family.setValue("Shmoe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
family.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><family value=\"Shmoe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension></family></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
}
@Test
public void testExtensions() throws DataFormatException {
@ -630,6 +540,7 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical());
}
@Test
public void testLoadAndEncodeUndeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException {
IParser p = ourCtx.newXmlParser();
@ -683,25 +594,6 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical());
}
@Test
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
//@formatter:off
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <identifier>\n" +
" <label value=\"IdentifierLabel\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue());
}
@Test
public void testLoadObservation() throws ConfigurationException, DataFormatException, IOException {
@ -767,6 +659,52 @@ public class XmlParserTest {
}
@Test
public void testMoreExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null);
ExtensionDt ext = new ExtensionDt();
ext.setModifier(false);
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.addUndeclaredExtension(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("given"));
given.addUndeclaredExtension(ext2);
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
}
@Test
public void testNarrativeGeneration() throws DataFormatException {
@ -791,14 +729,52 @@ public class XmlParserTest {
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str);
assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass());
assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass());
public void testNestedContainedResources() {
Observation A = new Observation();
A.getName().setText("A");
Observation B = new Observation();
B.getName().setText("B");
A.addRelated().setTarget(new ResourceReferenceDt(B));
Observation C = new Observation();
C.getName().setText("C");
B.addRelated().setTarget(new ResourceReferenceDt(C));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A);
ourLog.info(str);
assertThat(str, stringContainsInOrder(Arrays.asList("<text value=\"B\"/>", "<text value=\"C\"/>", "<text value=\"A\"/>")));
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>")));
// Only one (outer) contained block
int idx0 = str.indexOf("<contained>");
int idx1 = str.indexOf("<contained>",idx0+1);
assertNotEquals(-1, idx0);
assertEquals(-1, idx1);
Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
assertEquals("A",obs.getName().getText().getValue());
Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource();
assertEquals("B",obsB.getName().getText().getValue());
Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource();
assertEquals("C",obsC.getName().getText().getValue());
}
@Test
public void testParseBinaryResource() {
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
assertEquals("foo", val.getContentType());
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
}
@SuppressWarnings("deprecation")
@Test
public void testParseBundle() {
@ -813,7 +789,8 @@ public class XmlParserTest {
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title>FHIR Core Valuesets</title>\n" +
" <id>http://hl7.org/fhir/profile/valuesets</id>\n" +
" <link href=\"http://hl7.org/implement/standards/fhir/valuesets.xml\" rel=\"self\"/>\n" +
" <link href=\"http://hl7.org/implement/standards/fhir/valuesets.xml\" rel=\"self\"/>\n" +
" <category term=\"http://hl7.org/fhir/tag/message\" label=\"Message\" scheme=\"http://hl7.org/fhir/tag\"/>\n" +
" <updated>2014-02-10T04:11:24.435-00:00</updated>\n" +
" <entry>\n" +
" <title>Valueset &quot;256a5231-a2bb-49bd-9fea-f349d428b70d&quot; to support automated processing</title>\n" +
@ -867,6 +844,9 @@ public class XmlParserTest {
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Bundle bundle = p.parseBundle(msg);
assertEquals(1, bundle.getCategories().size());
assertEquals("http://hl7.org/fhir/tag", bundle.getCategories().get(0).getScheme());
assertEquals("FHIR Core Valuesets", bundle.getTitle().getValue());
assertEquals("http://hl7.org/implement/standards/fhir/valuesets.xml", bundle.getLinkSelf().getValue());
assertEquals("2014-02-10T04:11:24.435+00:00", bundle.getUpdated().getValueAsString());
@ -946,7 +926,6 @@ public class XmlParserTest {
}
@Test
public void testParseBundleLarge() throws IOException {
@ -960,6 +939,15 @@ public class XmlParserTest {
assertEquals("3216379", bundle.getEntries().get(0).getResource().getId().getIdPart());
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str);
assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass());
assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass());
}
@Test
public void testParseContainedResources() throws IOException {
@ -976,20 +964,7 @@ public class XmlParserTest {
}
/**
* This sample has extra elements in <searchParam> that are not actually a
* part of the spec any more..
*/
@Test
public void testParseFuroreMetadataWithExtraElements() throws IOException {
String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml"));
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Conformance conf = p.parseResource(Conformance.class, msg);
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
}
@Test
public void testParseEncodeNarrative() {
@ -1009,104 +984,67 @@ public class XmlParserTest {
assertThat(output, not(StringContainsInOrder.stringContainsInOrder(Arrays.asList("b xmlns"))));
}
/**
* This sample has extra elements in <searchParam> that are not actually a
* part of the spec any more..
*/
@Test
public void testParseFuroreMetadataWithExtraElements() throws IOException {
String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml"));
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Conformance conf = p.parseResource(Conformance.class, msg);
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
}
@Test
public void testParseLanguage() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\"><language value=\"zh-CN\"/><text><status value=\"generated\"/><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> 海生 <b>王 </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>URNo</td></tr><tr><td>Address</td><td><span>99 Houston Road </span><br/><span>BENTLEIGH </span><span>Victoria </span></td></tr><tr><td>Date of birth</td><td><span>01 January 1997</span></td></tr></tbody></table></div></text><identifier><use value=\"usual\"/><label value=\"URNo\"/><value value=\"89532\"/></identifier><name><text value=\"王海生\"/><family value=\"\"/><given value=\"海生\"/></name><telecom><system value=\"phone\"/><value value=\"9899 9878\"/><use value=\"home\"/></telecom><telecom><system value=\"email\"/><value value=\"zimmerman@datacorp.com.au\"/><use value=\"home\"/></telecom><gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\"/><code value=\"M\"/><display value=\"Male\"/></coding><text value=\"Male\"/></gender><birthDate value=\"1997-01-01\"/><address><use value=\"home\"/><text value=\"99 Houston Road, BENTLEIGH, 3204\"/><line value=\"99 Houston Road\"/><city value=\"BENTLEIGH\"/><state value=\"Victoria\"/><zip value=\"3204\"/><period><start value=\"2006-06-16\"/></period></address><active value=\"true\"/></Patient>";
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
assertEquals("zh-CN", pt.getLanguage().getValue());
}
@Test
public void testParseQuery() {
String msg = "<Query xmlns=\"http://hl7.org/fhir\">\n" +
" <text>\n" +
" <status value=\"generated\"/>\n" +
" <div xmlns=\"http://www.w3.org/1999/xhtml\">[Put rendering here]</div>\n" +
" </text>\n" +
"\n" +
" <!-- this is an extermely simple query - a request to execute the query 'example' on the\n" +
" responder -->\n" +
" <identifier value=\"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\"/>\n" +
" <parameter url=\"http://hl7.org/fhir/query#_query\">\n" +
" <valueString value=\"example\"/>\n" +
" </parameter>\n" +
"</Query>";
Query query = ourCtx.newXmlParser().parseResource(Query.class, msg);
assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString());
assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString());
assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString());
}
@BeforeClass
public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
ourCtx = new FhirContext();
}
@Test
public void testMoreExtensions() throws Exception {
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null);
ExtensionDt ext = new ExtensionDt();
ext.setModifier(false);
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.addUndeclaredExtension(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("given"));
given.addUndeclaredExtension(ext2);
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
}
@Test
public void testExtensionOnComposite() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
HumanNameDt given = name.addGiven("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
given.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension><family value=\"Shmoe\"/><given value=\"Joe\"/></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
}
@Test
public void testExtensionOnPrimitive() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
StringDt family = name.addFamily();
family.setValue("Shmoe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
family.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><family value=\"Shmoe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension></family></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
//@formatter:off
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <identifier>\n" +
" <label value=\"IdentifierLabel\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue());
}
@Test
@ -1167,4 +1105,71 @@ public class XmlParserTest {
}
@Test
public void testTagList() {
//@formatter:off
String tagListStr = "<taglist xmlns=\"http://hl7.org/fhir\"> \n" +
" <category term=\"term0\" label=\"label0\" scheme=\"scheme0\" /> \n" +
" <category term=\"term1\" label=\"label1\" scheme=\"\" /> \n" +
" <category term=\"term2\" label=\"label2\" /> \n" +
"</taglist>";
//@formatter:on
TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr);
assertEquals(3, tagList.size());
assertEquals("term0", tagList.get(0).getTerm());
assertEquals("label0", tagList.get(0).getLabel());
assertEquals("scheme0", tagList.get(0).getScheme());
assertEquals("term1", tagList.get(1).getTerm());
assertEquals("label1", tagList.get(1).getLabel());
assertEquals(null, tagList.get(1).getScheme());
assertEquals("term2", tagList.get(2).getTerm());
assertEquals("label2", tagList.get(2).getLabel());
assertEquals(null, tagList.get(2).getScheme());
/*
* Encode
*/
//@formatter:off
String expected = "<taglist xmlns=\"http://hl7.org/fhir\">" +
"<category term=\"term0\" label=\"label0\" scheme=\"scheme0\"/>" +
"<category term=\"term1\" label=\"label1\"/>" +
"<category term=\"term2\" label=\"label2\"/>" +
"</taglist>";
//@formatter:on
String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList);
assertEquals(expected,encoded);
}
@Test
public void testTotalResultsUsingOldNamespace() {
//@formatter:off
String bundle = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title>Search results for Patient</title>\n" +
" <id>urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8</id>\n" +
" <totalResults xmlns=\"http://purl.org/atompub/tombstones/1.0\">15</totalResults>\n" +
" <updated>2014-05-04T13:19:47.027-04:00</updated>\n" +
" <author>\n" +
" <name>AEGIS Wildfhir Server</name>\n" +
" </author>" +
"</feed>";
//@formatter:off
Bundle bundleR = ourCtx.newXmlParser().parseBundle(bundle);
assertEquals(15, bundleR.getTotalResults().getValue().intValue());
}
@BeforeClass
public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
ourCtx = new FhirContext();
}
}

View File

@ -25,6 +25,11 @@
}
],
"updated" : "2014-03-22T15:37:12Z",
"category" : [{
"term" : "http://term",
"label" : "label",
"scheme" : "http://scheme"
}],
"totalResults" : "356",
"entry" : [
{