From 598eec53ed6e2c34e8e3d055f2268dd12a634864 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Tue, 19 Aug 2014 07:48:06 -0400 Subject: [PATCH] Add model visitor, and allow bundles to have categories (as allowed in the spec) --- .../java/example/GenericClientExample.java | 19 +- hapi-fhir-base/src/changes/changes.xml | 4 + .../java/ca/uhn/fhir/model/api/Bundle.java | 103 ++- .../java/ca/uhn/fhir/parser/JsonParser.java | 28 +- .../java/ca/uhn/fhir/parser/ParserState.java | 42 +- .../java/ca/uhn/fhir/parser/XmlParser.java | 24 +- .../java/ca/uhn/fhir/util/FhirTerser.java | 90 +- .../java/ca/uhn/fhir/util/IModelVisitor.java | 33 + .../src/site/xdoc/doc_rest_client.xml | 33 +- .../uhn/fhir/context/ModelExtensionTest.java | 5 +- .../ca/uhn/fhir/parser/JsonParserTest.java | 29 +- .../ca/uhn/fhir/parser/XmlParserTest.java | 845 +++++++++--------- .../test/resources/atom-document-large.json | 5 + 13 files changed, 706 insertions(+), 554 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java diff --git a/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java b/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java index 97920283720..4805c3f3411 100644 --- a/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java +++ b/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java @@ -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 response = client.transaction() } public static void main(String[] args) { - // nothing + simpleExample(); } } diff --git a/hapi-fhir-base/src/changes/changes.xml b/hapi-fhir-base/src/changes/changes.xml index 7dbf5aeaac1..86b19826573 100644 --- a/hapi-fhir-base/src/changes/changes.xml +++ b/hapi-fhir-base/src/changes/changes.xml @@ -87,6 +87,10 @@ Transaction method in server can now have parameter type Bundle instead of List<IResource> + + HAPI parsers now use field access to get/set values instead of method accessors and mutators. + This should give a small performance boost. + diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java index 6046f7ed0bc..8db3a1aeba1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java @@ -44,11 +44,6 @@ public class Bundle extends BaseBundle /* implements IElement */{ private volatile transient Map myIdToEntries; - //@formatter:off - /* **************************************************** - * NB: add any new fields to the isEmpty() method!!! - *****************************************************/ - //@formatter:on private List 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. *

- * Important usage notes: This method ignores base URLs (so passing in an ID of http://foo/Patient/123 will return a resource if it has the logical ID of - * http://bar/Patient/123. 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. + * Important usage notes: This method ignores base URLs (so passing in an ID of + * http://foo/Patient/123 will return a resource if it has the logical ID of + * http://bar/Patient/123. 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. *

* - * @param theId The resource ID + * @param theId + * The resource ID * @return Returns the resource with the given ID, or null 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 = "\n" + -// " \n" + -// " \n" + -// " \n" + -// " \n" + -// " \n" + -// "
\n" + -// " \n" + -// " \n" + -// " \n" + -// " \n" + -// " \n" + -// ""; -// -// 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 = "\n" + + // " \n" + + // " \n" + + // " \n" + + // " \n" + + // " \n" + + // "
\n" + + // " \n" + + // " \n" + + // " \n" + + // " \n" + + // " \n" + + // ""; + // + // 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 getEntries() { if (myEntries == null) { myEntries = new ArrayList(); @@ -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); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index fae9a39f18a..ec24845d9fe 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -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 { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index 91dba069f02..a78a5679161 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -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 { @@ -628,6 +628,8 @@ class ParserState { 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 { 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 { 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); + } + } } } } - } - + }); + } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java index 571dd838bc8..06a8339b0d9 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java @@ -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) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index 1aa4144ff21..0731c45aa86 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -108,30 +108,64 @@ public class FhirTerser { } /** - * Returns a list containing all child elements (including the resource itself) which are non-empty - * 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 non-empty and are + * either of the exact type specified, or are a subclass of that type. *

- * 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. - *

- * @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. + *

+ * + * @param theResourceT + * The resource instance to search. Must not be null. + * @param theType + * The type to search for. Must not be null. * @return */ - public List getAllPopulatedChildElementsOfType(IResource theResource, Class theType) { - ArrayList retVal = new ArrayList(); + public List getAllPopulatedChildElementsOfType(IResource theResource, final Class theType) { + final ArrayList retVal = new ArrayList(); 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 void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition theDefinition, Class theType, ArrayList theList) { - if (theElement.isEmpty()) { - return; - } - - addIfCorrectType(theElement, theType, theList); - addUndeclaredExtensions(theElement, theType, theList); + private 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 void addUndeclaredExtensions(IElement theElement, Class theType, ArrayList theList) { + private 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 void addIfCorrectType(IElement theElement, Class theType, ArrayList theList) { - if (theElement != null && theType.isAssignableFrom(theElement.getClass())) { - theList.add((T) theElement); - } - } - } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java new file mode 100644 index 00000000000..e8b013f20a3 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java @@ -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); + + + +} diff --git a/hapi-fhir-base/src/site/xdoc/doc_rest_client.xml b/hapi-fhir-base/src/site/xdoc/doc_rest_client.xml index ce039e65566..9f2f9fc7f39 100644 --- a/hapi-fhir-base/src/site/xdoc/doc_rest_client.xml +++ b/hapi-fhir-base/src/site/xdoc/doc_rest_client.xml @@ -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.

@@ -75,21 +76,13 @@ such as encodedJson() or encodedXml().

- - -

- The following example shows how to perform a create - operation using the generic client: -

- - - - -
+

+ Searching for resources is probably the most common initial scenario for + client applications, so we'll start the demonstration there. +

The following example shows how to query using the generic client:

@@ -173,6 +166,18 @@
+ +

+ The following example shows how to perform a create + operation using the generic client: +

+ + + + +
+

The following example shows how to perform a delete diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/ModelExtensionTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/ModelExtensionTest.java index 409dc922799..d593c274a09 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/ModelExtensionTest.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/ModelExtensionTest.java @@ -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()); } } diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java index b5f7d601f2f..8adc7ad59ef 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java @@ -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); diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java index 122b1e50194..c2cdae24476 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java @@ -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 = "

海生
IdentifierURNo
Address99 Houston Road
BENTLEIGH Victoria
Date of birth01 January 1997
"; - 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("AQIDBA==", 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("", "", ""))); - assertThat(str, stringContainsInOrder(Arrays.asList("", ""))); - - // Only one (outer) contained block - int idx0 = str.indexOf(""); - int idx1 = str.indexOf("",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 = "\n" + - " \n" + - " \n" + - "
[Put rendering here]
\n" + - "
\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
"; - 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("", 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("AQIDBA==", val); - - } - - - @Test - public void testParseBinaryResource() { - - Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "AQIDBA=="); - assertEquals("foo", val.getContentType()); - assertArrayEquals(new byte[] {1,2,3,4}, val.getContent()); - - } - - @Test - public void testTagList() { - - //@formatter:off - String tagListStr = " \n" + - " \n" + - " \n" + - " \n" + - ""; - //@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 = "" + - "" + - "" + - "" + - ""; - //@formatter:on - - String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList); - assertEquals(expected,encoded); - - } - - - @Test - public void testTotalResultsUsingOldNamespace() { - - //@formatter:off - String bundle = "\n" + - " Search results for Patient\n" + - " urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8\n" + - " 15\n" + - " 2014-05-04T13:19:47.027-04:00\n" + - " \n" + - " AEGIS Wildfhir Server\n" + - " " + - ""; - //@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("")); - - Patient actual = parser.parseResource(Patient.class, val); - assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); - List 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("")); - - 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("")); - - 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("")); - - 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("123")); - - } - - @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("")); - - 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 strings = new ArrayList(); strings.addAll(Arrays.asList("", pub.getValueAsString(), "")); + strings.add(""); strings.addAll(Arrays.asList("", "1", "")); strings.addAll(Arrays.asList("", "2", "", "","")); strings.addAll(Arrays.asList("")); @@ -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("")); + + 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("123")); + + } + + @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("")); + + 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("")); + + 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("")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + List 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("", 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("")); + + 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("")); + + 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("")); + + 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 = "" + - "\n" + - " \n" + - " \n" + - ""; - //@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("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + } + + @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("", "", ""))); + assertThat(str, stringContainsInOrder(Arrays.asList("", ""))); + + // Only one (outer) contained block + int idx0 = str.indexOf(""); + int idx1 = str.indexOf("",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, "AQIDBA=="); + 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 = "\n" + " FHIR Core Valuesets\n" + " http://hl7.org/fhir/profile/valuesets\n" + - " \n" + + " \n" + + " \n" + " 2014-02-10T04:11:24.435-00:00\n" + " \n" + " Valueset "256a5231-a2bb-49bd-9fea-f349d428b70d" to support automated processing\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 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 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 = "
海生
IdentifierURNo
Address99 Houston Road
BENTLEIGH Victoria
Date of birth01 January 1997
"; + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + assertEquals("zh-CN", pt.getLanguage().getValue()); + } + + @Test + public void testParseQuery() { + String msg = "\n" + + " \n" + + " \n" + + "
[Put rendering here]
\n" + + "
\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
"; + 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("")); - assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - } - - @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("")); - - 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("")); - - 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 = "" + + "\n" + + " \n" + + " \n" + + ""; + //@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 = " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@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 = "" + + "" + + "" + + "" + + ""; + //@formatter:on + + String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList); + assertEquals(expected,encoded); + + } + + @Test + public void testTotalResultsUsingOldNamespace() { + + //@formatter:off + String bundle = "\n" + + " Search results for Patient\n" + + " urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8\n" + + " 15\n" + + " 2014-05-04T13:19:47.027-04:00\n" + + " \n" + + " AEGIS Wildfhir Server\n" + + " " + + ""; + //@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(); + } + } diff --git a/hapi-fhir-base/src/test/resources/atom-document-large.json b/hapi-fhir-base/src/test/resources/atom-document-large.json index 59ca6cca251..e1fbe3a9a38 100644 --- a/hapi-fhir-base/src/test/resources/atom-document-large.json +++ b/hapi-fhir-base/src/test/resources/atom-document-large.json @@ -25,6 +25,11 @@ } ], "updated" : "2014-03-22T15:37:12Z", + "category" : [{ + "term" : "http://term", + "label" : "label", + "scheme" : "http://scheme" + }], "totalResults" : "356", "entry" : [ {