From f2ba56af2f153b900896c77cddd83b3216f6df86 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Fri, 14 Mar 2014 08:57:30 -0400 Subject: [PATCH] Start JSON parser --- .../context/BaseRuntimeChildDefinition.java | 4 + .../java/ca/uhn/fhir/context/FhirContext.java | 5 + ...imeChildUndeclaredExtensionDefinition.java | 14 + .../api/ISupportsUndeclaredExtensions.java | 2 +- .../model/api/annotation/ResourceDef.java | 2 +- .../ca/uhn/fhir/parser/CopyOfJsonParser.java | 391 ++++++++++++++++++ .../main/java/ca/uhn/fhir/parser/IParser.java | 13 +- .../java/ca/uhn/fhir/parser/JsonParser.java | 355 ++++++++++++++++ .../java/ca/uhn/fhir/parser/XmlParser.java | 42 +- .../java/example/FhirContextIntro.java | 5 +- .../RuntimeResourceDefinitionTest.java | 7 +- .../ca/uhn/fhir/parser/JsonParserTest.java | 27 ++ .../ca/uhn/fhir/parser/XmlParserTest.java | 23 ++ .../java/ca/uhn/fhir/rest/client/Tester.java | 5 +- .../ca/uhn/fhir/testmodel/IdentifierDt.java | 391 ++++++++++++++++++ .../java/ca/uhn/fhir/testmodel/Patient.java | 101 +++++ .../resources/example-patient-general.xml | 114 +++++ .../resources/observation-example-eeg.xml | 7 +- 18 files changed, 1451 insertions(+), 57 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/CopyOfJsonParser.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/IdentifierDt.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/Patient.java create mode 100644 hapi-fhir-base/src/test/resources/example-patient-general.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java index db5d22fdb51..15207b030a9 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeChildDefinition.java @@ -26,6 +26,10 @@ public abstract class BaseRuntimeChildDefinition { List getValues(Object theTarget); } + public abstract int getMax(); + + public abstract int getMin(); + public interface IMutator { void addValue(Object theTarget, IElement theValue); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java index f7f7fb50ceb..6c98bb9b3fa 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java @@ -9,6 +9,7 @@ import java.util.Map; import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.JsonParser; import ca.uhn.fhir.parser.XmlParser; import ca.uhn.fhir.rest.client.IRestfulClientFactory; import ca.uhn.fhir.rest.client.RestfulClientFactory; @@ -92,4 +93,8 @@ public class FhirContext { return myIdToResourceDefinition.values(); } + public IParser newJsonParser() { + return new JsonParser(this); + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java index 057ce9e7b37..3541895a383 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java @@ -13,6 +13,7 @@ import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.BaseResourceReference; import ca.uhn.fhir.model.api.UndeclaredExtension; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildDefinition { @@ -77,6 +78,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD def.sealAndInitialize(theClassToElementDefinitions); myAttributeNameToDefinition.put("valueResource", def); myDatatypeToDefinition.put(BaseResourceReference.class, def); + myDatatypeToDefinition.put(ResourceReferenceDt.class, def); } @@ -109,4 +111,16 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD } + @Override + public int getMax() { + return 1; + } + + + @Override + public int getMin() { + return 0; + } + + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java index 6866d0495bc..d5ffdfed423 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java @@ -2,7 +2,7 @@ package ca.uhn.fhir.model.api; import java.util.List; -public interface ISupportsUndeclaredExtensions { +public interface ISupportsUndeclaredExtensions extends IElement { /** * Returns a list containing all undeclared non-modifier extensions diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java index c7a1c8c9da4..5d706809600 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java @@ -13,7 +13,7 @@ public @interface ResourceDef { String name(); - String id(); + String id() default ""; String profile() default ""; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/CopyOfJsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/CopyOfJsonParser.java new file mode 100644 index 00000000000..05cda924697 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/CopyOfJsonParser.java @@ -0,0 +1,391 @@ +package ca.uhn.fhir.parser; + + +public class CopyOfJsonParser { + +// private FhirContext myContext; +// +// public CopyOfJsonParser(FhirContext theContext) { +// myContext = theContext; +// } +// +// @Override +// public String encodeBundleToString(Bundle theBundle) throws DataFormatException { +// StringWriter stringWriter = new StringWriter(); +// encodeBundleToWriter(theBundle, stringWriter); +// +// return stringWriter.toString(); +// } +// +// @Override +// public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) { +// try { +// XMLStreamWriter eventWriter; +// eventWriter = myXmlOutputFactory.createXMLStreamWriter(theWriter); +// eventWriter = decorateStreamWriter(eventWriter); +// +// eventWriter.writeStartElement("feed"); +// eventWriter.writeDefaultNamespace(ATOM_NS); +// +// writeTagWithTextNode(eventWriter, "title", theBundle.getTitle()); +// writeTagWithTextNode(eventWriter, "id", theBundle.getId()); +// +// writeAtomLink(eventWriter, "self", theBundle.getLinkSelf()); +// writeAtomLink(eventWriter, "first", theBundle.getLinkFirst()); +// writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious()); +// writeAtomLink(eventWriter, "next", theBundle.getLinkNext()); +// writeAtomLink(eventWriter, "last", theBundle.getLinkLast()); +// writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase()); +// +// if (theBundle.getTotalResults().getValue() != null) { +// eventWriter.writeStartElement("os", OPENSEARCH_NS, "totalResults"); +// eventWriter.writeNamespace("os", OPENSEARCH_NS); +// eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString()); +// eventWriter.writeEndElement(); +// } +// +// writeOptionalTagWithTextNode(eventWriter, "updated", theBundle.getUpdated()); +// writeOptionalTagWithTextNode(eventWriter, "published", theBundle.getPublished()); +// +// if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) { +// eventWriter.writeStartElement("author"); +// writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName()); +// writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri()); +// eventWriter.writeEndElement(); +// } +// +// for (BundleEntry nextEntry : theBundle.getEntries()) { +// eventWriter.writeStartElement("entry"); +// +// eventWriter.writeStartElement("content"); +// eventWriter.writeAttribute("type", "text/xml"); +// +// IResource resource = nextEntry.getResource(); +// encodeResourceToXmlStreamWriter(resource, eventWriter); +// +// eventWriter.writeEndElement(); // content +// eventWriter.writeEndElement(); // entry +// } +// +// eventWriter.writeEndElement(); +// eventWriter.close(); +// } catch (XMLStreamException e) { +// throw new ConfigurationException("Failed to initialize STaX event factory", e); +// } +// } +// +// private void encodeChildElementToStreamWriter(JsonWriter theEventWriter, IElement nextValue, String childName, BaseRuntimeElementDefinition childDef, String theExtensionUrl) { +// if (nextValue.isEmpty()) { +// return; +// } +// +// switch (childDef.getChildType()) { +// case PRIMITIVE_DATATYPE: { +// IPrimitiveDatatype pd = (IPrimitiveDatatype) nextValue; +// if (pd.getValue() != null) { +// theEventWriter.name(childName); +// if (pd instanceof IntegerDt) { +// theEventWriter.value(((IntegerDt)pd).getValue()); +// } else if (pd instanceof DecimalDt) { +// theEventWriter.value(((DecimalDt)pd).getValue()); +// } else if (pd instanceof BooleanDt) { +// theEventWriter.value(((BooleanDt)pd).getValue()); +// } else { +// String value = pd.getValueAsString(); +// theEventWriter.value(value); +// } +// theEventWriter.writeAttribute("value", value); +// encodeExtensionsIfPresent(theEventWriter, nextValue); +// theEventWriter.writeEndElement(); +// } +// break; +// } +// case RESOURCE_BLOCK: +// case COMPOSITE_DATATYPE: { +// theEventWriter.writeStartElement(childName); +// if (isNotBlank(theExtensionUrl)) { +// theEventWriter.writeAttribute("url", theExtensionUrl); +// } +// BaseRuntimeElementCompositeDefinition childCompositeDef = (BaseRuntimeElementCompositeDefinition) childDef; +// encodeCompositeElementToStreamWriter(nextValue, theEventWriter, childCompositeDef); +// encodeExtensionsIfPresent(theEventWriter, nextValue); +// theEventWriter.writeEndElement(); +// break; +// } +// case RESOURCE_REF: { +// ResourceReferenceDt ref = (ResourceReferenceDt) nextValue; +// if (!ref.isEmpty()) { +// theEventWriter.writeStartElement(childName); +// encodeResourceReferenceToStreamWriter(theEventWriter, ref); +// theEventWriter.writeEndElement(); +// } +// break; +// } +// case RESOURCE: { +// throw new IllegalStateException(); // should not happen +// } +// case PRIMITIVE_XHTML: { +// XhtmlDt dt = (XhtmlDt) nextValue; +// if (dt.hasContent()) { +// encodeXhtml(dt, theEventWriter); +// } +// break; +// } +// case UNDECL_EXT: { +// throw new IllegalStateException("should not happen"); +// } +// } +// +// } +// +// private void encodeCompositeElementChildrenToStreamWriter(IElement theElement, XMLStreamWriter theEventWriter, List children) throws XMLStreamException, +// DataFormatException { +// for (BaseRuntimeChildDefinition nextChild : children) { +// List values = nextChild.getAccessor().getValues(theElement); +// if (values == null || values.isEmpty()) { +// continue; +// } +// +// for (IElement nextValue : values) { +// if (nextValue == null) { +// continue; +// } +// Class type = nextValue.getClass(); +// String childName = nextChild.getChildNameByDatatype(type); +// String extensionUrl = nextChild.getExtensionUrl(); +// BaseRuntimeElementDefinition childDef = nextChild.getChildElementDefinitionByDatatype(type); +// if (childDef == null) { +// throw new IllegalStateException(nextChild + " has no child of type " + type); +// } +// +// if (extensionUrl != null && childName.equals("extension") == false) { +// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild; +// if (extDef.isModifier()) { +// theEventWriter.writeStartElement("modifierExtension"); +// }else { +// theEventWriter.writeStartElement("extension"); +// } +// +// theEventWriter.writeAttribute("url", extensionUrl); +// encodeChildElementToStreamWriter(theEventWriter, nextValue, childName, childDef, null); +// theEventWriter.writeEndElement(); +// } else { +// encodeChildElementToStreamWriter(theEventWriter, nextValue, childName, childDef, extensionUrl); +// } +// } +// } +// } +// +// private void encodeCompositeElementToStreamWriter(IElement theElement, JsonWriter theEventWriter, BaseRuntimeElementCompositeDefinition resDef) throws XMLStreamException, +// DataFormatException { +// encodeExtensionsIfPresent(theEventWriter, theElement); +// encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getExtensions()); +// encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getChildren()); +// } +// +// private void encodeExtensionsIfPresent(JsonWriter theWriter, IElement theResource) { +// if (theResource instanceof ISupportsUndeclaredExtensions) { +// ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theResource; +// encodeUndeclaredExtensions(theWriter, res.getUndeclaredExtensions(), "extension"); +// encodeUndeclaredExtensions(theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension"); +// } +// } +// +// private void encodeUndeclaredExtensions(JsonWriter theWriter, List extensions, String theTagName) throws XMLStreamException { +// if (extensions.isEmpty()) { +// return; +// } +// +// theWriter.name(theTagName); +// theWriter.beginArray(); +// +// for (UndeclaredExtension next : extensions) { +// theWriter.name("url"); +// theWriter.value(next.getUrl()); +// +// if (next.getValue() != null) { +// IElement nextValue = next.getValue(); +// RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition(); +// String childName = extDef.getChildNameByDatatype(nextValue.getClass()); +// BaseRuntimeElementDefinition childDef = extDef.getChildElementDefinitionByDatatype(nextValue.getClass()); +// encodeChildElementToStreamWriter(theWriter, nextValue, childName, childDef, null); +// } +// +// // child extensions +// encodeExtensionsIfPresent(theWriter, next); +// +// } +// +// theWriter.endArray(); +// } +// +// private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, ResourceReferenceDt theRef) throws XMLStreamException { +// if (!(theRef.getDisplay().isEmpty())) { +// theEventWriter.writeStartElement("display"); +// theEventWriter.writeAttribute("value", theRef.getDisplay().getValue()); +// theEventWriter.writeEndElement(); +// } +// if (!(theRef.getReference().isEmpty())) { +// theEventWriter.writeStartElement("reference"); +// theEventWriter.writeAttribute("value", theRef.getReference().getValue()); +// theEventWriter.writeEndElement(); +// } +// } +// +// +// @Override +// public String encodeResourceToString(IResource theResource) throws DataFormatException { +// Writer stringWriter = new StringWriter(); +// encodeResourceToWriter(theResource, stringWriter); +// return stringWriter.toString(); +// } +// +// @Override +// public void encodeResourceToWriter(IResource theResource, Writer theWriter) { +// JsonWriter eventWriter = new JsonWriter(theWriter); +//// try { +// encodeResourceToXmlStreamWriter(theResource, eventWriter); +// eventWriter.flush(); +//// } catch (XMLStreamException e) { +//// throw new ConfigurationException("Failed to initialize STaX event factory", e); +//// } +// } +// +// +// private void encodeResourceToXmlStreamWriter(IResource theResource, JsonWriter theEventWriter) throws XMLStreamException, DataFormatException { +// RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource); +// +// theEventWriter.beginObject(); +// +// theEventWriter.name("resourceType"); +// theEventWriter.value(resDef.getName()); +// +// encodeCompositeElementToStreamWriter(theResource, theEventWriter, resDef); +// +// theEventWriter.writeEndElement(); +// } +// +// private void encodeXhtml(XhtmlDt theDt, XMLStreamWriter theEventWriter) throws XMLStreamException { +// if (theDt == null || theDt.getValue() == null) { +// return; +// } +// +// boolean firstEvent = true; +// for (XMLEvent event : theDt.getValue()) { +// switch (event.getEventType()) { +// case XMLStreamConstants.ATTRIBUTE: +// Attribute attr = (Attribute) event; +// if (isBlank(attr.getName().getPrefix())) { +// if (isBlank(attr.getName().getNamespaceURI())) { +// theEventWriter.writeAttribute(attr.getName().getLocalPart(), attr.getValue()); +// } else { +// theEventWriter.writeAttribute(attr.getName().getNamespaceURI(), attr.getName().getLocalPart(), attr.getValue()); +// } +// } else { +// theEventWriter.writeAttribute(attr.getName().getPrefix(), attr.getName().getNamespaceURI(), attr.getName().getLocalPart(), attr.getValue()); +// } +// +// break; +// case XMLStreamConstants.CDATA: +// theEventWriter.writeCData(((Characters) event).getData()); +// break; +// case XMLStreamConstants.CHARACTERS: +// case XMLStreamConstants.SPACE: +// theEventWriter.writeCharacters(((Characters) event).getData()); +// break; +// case XMLStreamConstants.COMMENT: +// theEventWriter.writeComment(((Comment) event).getText()); +// break; +// case XMLStreamConstants.END_ELEMENT: +// theEventWriter.writeEndElement(); +// break; +// case XMLStreamConstants.ENTITY_REFERENCE: +// EntityReference er = (EntityReference) event; +// theEventWriter.writeEntityRef(er.getName()); +// break; +// case XMLStreamConstants.NAMESPACE: +// Namespace ns = (Namespace) event; +// theEventWriter.writeNamespace(ns.getPrefix(), ns.getNamespaceURI()); +// break; +// case XMLStreamConstants.START_ELEMENT: +// StartElement se = event.asStartElement(); +// if (firstEvent) { +// theEventWriter.writeStartElement(se.getName().getLocalPart()); +// if (StringUtils.isBlank(se.getName().getPrefix())) { +// theEventWriter.writeDefaultNamespace(se.getName().getNamespaceURI()); +// } else { +// theEventWriter.writeNamespace(se.getName().getPrefix(), se.getName().getNamespaceURI()); +// } +// } else { +// if (isBlank(se.getName().getPrefix())) { +// if (isBlank(se.getName().getNamespaceURI())) { +// theEventWriter.writeStartElement(se.getName().getLocalPart()); +// } else { +// if (StringUtils.isBlank(se.getName().getPrefix())) { +// theEventWriter.writeStartElement(se.getName().getLocalPart()); +// theEventWriter.writeDefaultNamespace(se.getName().getNamespaceURI()); +// } else { +// theEventWriter.writeStartElement(se.getName().getNamespaceURI(), se.getName().getLocalPart()); +// } +// } +// } else { +// theEventWriter.writeStartElement(se.getName().getPrefix(), se.getName().getLocalPart(), se.getName().getNamespaceURI()); +// } +// } +// break; +// case XMLStreamConstants.DTD: +// case XMLStreamConstants.END_DOCUMENT: +// case XMLStreamConstants.ENTITY_DECLARATION: +// case XMLStreamConstants.NOTATION_DECLARATION: +// case XMLStreamConstants.PROCESSING_INSTRUCTION: +// case XMLStreamConstants.START_DOCUMENT: +// break; +// } +// +// firstEvent = false; +// } +// } +// +// @Override +// public Bundle parseBundle(Reader theReader) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public Bundle parseBundle(String theMessageString) throws ConfigurationException, DataFormatException { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public IResource parseResource(XMLEventReader theStreamReader) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public T parseResource(Class theResourceType, String theMessageString) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public IResource parseResource(Class theResourceType, Reader theReader) { +// // TODO Auto-generated method stub +// return null; +// } + +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java index 1e9ca060bbf..61aa47a9f59 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java @@ -1,12 +1,9 @@ package ca.uhn.fhir.parser; +import java.io.IOException; import java.io.Reader; import java.io.Writer; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.IResource; @@ -17,11 +14,9 @@ public interface IParser { void encodeBundleToWriter(Bundle theBundle, Writer theWriter); - String encodeResourceToString(IResource theResource) throws DataFormatException; + String encodeResourceToString(IResource theResource) throws DataFormatException, IOException; - void encodeResourceToWriter(IResource theResource, Writer stringWriter); - - void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException; + void encodeResourceToWriter(IResource theResource, Writer stringWriter) throws IOException; Bundle parseBundle(Reader theReader); @@ -31,8 +26,6 @@ public interface IParser { IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException; - IResource parseResource(XMLEventReader theStreamReader); - T parseResource(Class theResourceType, String theMessageString); IResource parseResource(Class theResourceType, Reader theReader); 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 new file mode 100644 index 00000000000..df7130821db --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -0,0 +1,355 @@ +package ca.uhn.fhir.parser; + +import static org.apache.commons.lang3.StringUtils.*; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import org.apache.commons.lang3.StringUtils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.stream.JsonWriter; + +import ca.uhn.fhir.context.BaseRuntimeChildDefinition; +import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; +import ca.uhn.fhir.context.BaseRuntimeElementDefinition; +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; +import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition; +import ca.uhn.fhir.context.RuntimeResourceDefinition; +import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.BundleEntry; +import ca.uhn.fhir.model.api.ICompositeDatatype; +import ca.uhn.fhir.model.api.IElement; +import ca.uhn.fhir.model.api.IPrimitiveDatatype; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions; +import ca.uhn.fhir.model.api.UndeclaredExtension; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.primitive.BooleanDt; +import ca.uhn.fhir.model.primitive.DecimalDt; +import ca.uhn.fhir.model.primitive.IntegerDt; +import ca.uhn.fhir.model.primitive.XhtmlDt; + +public class JsonParser implements IParser { + + private FhirContext myContext; + + public JsonParser(FhirContext theContext) { + myContext = theContext; + } + + @Override + public String encodeBundleToString(Bundle theBundle) throws DataFormatException { + StringWriter stringWriter = new StringWriter(); + encodeBundleToWriter(theBundle, stringWriter); + + return stringWriter.toString(); + } + + @Override + public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) { + // try { + // XMLStreamWriter eventWriter; + // eventWriter = myXmlOutputFactory.createXMLStreamWriter(theWriter); + // eventWriter = decorateStreamWriter(eventWriter); + // + // eventWriter.writeStartElement("feed"); + // eventWriter.writeDefaultNamespace(ATOM_NS); + // + // writeTagWithTextNode(eventWriter, "title", theBundle.getTitle()); + // writeTagWithTextNode(eventWriter, "id", theBundle.getId()); + // + // writeAtomLink(eventWriter, "self", theBundle.getLinkSelf()); + // writeAtomLink(eventWriter, "first", theBundle.getLinkFirst()); + // writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious()); + // writeAtomLink(eventWriter, "next", theBundle.getLinkNext()); + // writeAtomLink(eventWriter, "last", theBundle.getLinkLast()); + // writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase()); + // + // if (theBundle.getTotalResults().getValue() != null) { + // eventWriter.writeStartElement("os", OPENSEARCH_NS, "totalResults"); + // eventWriter.writeNamespace("os", OPENSEARCH_NS); + // eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString()); + // eventWriter.writeEndElement(); + // } + // + // writeOptionalTagWithTextNode(eventWriter, "updated", + // theBundle.getUpdated()); + // writeOptionalTagWithTextNode(eventWriter, "published", + // theBundle.getPublished()); + // + // if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) { + // eventWriter.writeStartElement("author"); + // writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName()); + // writeOptionalTagWithTextNode(eventWriter, "uri", + // theBundle.getAuthorUri()); + // eventWriter.writeEndElement(); + // } + // + // for (BundleEntry nextEntry : theBundle.getEntries()) { + // eventWriter.writeStartElement("entry"); + // + // eventWriter.writeStartElement("content"); + // eventWriter.writeAttribute("type", "text/xml"); + // + // IResource resource = nextEntry.getResource(); + // encodeResourceToJsonStreamWriter(resource, eventWriter); + // + // eventWriter.writeEndElement(); // content + // eventWriter.writeEndElement(); // entry + // } + // + // eventWriter.writeEndElement(); + // eventWriter.close(); + // } catch (XMLStreamException e) { + // throw new + // ConfigurationException("Failed to initialize STaX event factory", e); + // } + } + + private void encodeCompositeElementToStreamWriter(IElement theElement, JsonWriter theEventWriter, BaseRuntimeElementCompositeDefinition resDef) throws IOException, DataFormatException { + encodeExtensionsIfPresent(theEventWriter, theElement); + encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getExtensions()); + encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getChildren()); + } + + private void encodeCompositeElementChildrenToStreamWriter(IElement theElement, JsonWriter theEventWriter, List theChildren) throws IOException { + for (BaseRuntimeChildDefinition nextChild : theChildren) { + List values = nextChild.getAccessor().getValues(theElement); + if (values == null || values.isEmpty()) { + continue; + } + + String currentChildName = null; + boolean inArray = false; + + IElement[] extensions = new IElement[values.size()]; + IElement[] modifierExtensions = new IElement[values.size()]; + boolean haveExtensions = false; + boolean haveModifierExtensions = false; + + for (IElement nextValue : values) { + if (nextValue == null || nextValue.isEmpty()) { + continue; + } + + Class type = nextValue.getClass(); + String childName = nextChild.getChildNameByDatatype(type); + String extensionUrl = nextChild.getExtensionUrl(); + BaseRuntimeElementDefinition childDef = nextChild.getChildElementDefinitionByDatatype(type); + if (childDef == null) { + throw new IllegalStateException(nextChild + " has no child of type " + type); + } + + if (extensionUrl != null && childName.equals("extension") == false) { + + RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild; + if (extDef.isModifier()) { + theEventWriter.name("modifierExtension"); + } else { + theEventWriter.name("extension"); + } + + theEventWriter.beginObject(); + theEventWriter.name("url"); + theEventWriter.value(extensionUrl); + theEventWriter.name(childName); + encodeChildElementToStreamWriter(theEventWriter, nextValue, childName, childDef); + theEventWriter.endObject(); + + } else { + + if (currentChildName == null || !currentChildName.equals(childName)) { + if (inArray) { + theEventWriter.endArray(); + } + theEventWriter.name(childName); + if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED){ + theEventWriter.beginArray(); + inArray = true; + } + currentChildName = childName; + } + + encodeChildElementToStreamWriter(theEventWriter, nextValue, childName, childDef); + } + } + + + + if (inArray) { + theEventWriter.endArray(); + } + } + } + + private void encodeExtensionsIfPresent(JsonWriter theWriter, IElement theResource) throws IOException { + if (theResource instanceof ISupportsUndeclaredExtensions) { + ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theResource; + encodeUndeclaredExtensions(theWriter, res.getUndeclaredExtensions(), "extension"); + encodeUndeclaredExtensions(theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension"); + } + } + + private void encodeUndeclaredExtensions(JsonWriter theWriter, List extensions, String theTagName) throws IOException { + if (extensions.isEmpty()) { + return; + } + + theWriter.name(theTagName); + theWriter.beginArray(); + + for (UndeclaredExtension next : extensions) { + + theWriter.beginObject(); + theWriter.name("url"); + theWriter.value(next.getUrl()); + + if (next.getValue() != null) { + IElement nextValue = next.getValue(); + RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition(); + String childName = extDef.getChildNameByDatatype(nextValue.getClass()); + BaseRuntimeElementDefinition childDef = extDef.getChildElementDefinitionByDatatype(nextValue.getClass()); + encodeChildElementToStreamWriter(theWriter, nextValue, childName, childDef); + } + + encodeUndeclaredExtensions(theWriter, next.getUndeclaredExtensions(), "extension"); + encodeUndeclaredExtensions(theWriter, next.getUndeclaredModifierExtensions(), "modifierExtension"); + + theWriter.endObject(); + } + + theWriter.endArray(); + } + + private void encodeChildElementToStreamWriter(JsonWriter theWriter, IElement theValue, String theChildName, BaseRuntimeElementDefinition theChildDef) throws IOException { + + switch (theChildDef.getChildType()) { + case PRIMITIVE_DATATYPE: { + IPrimitiveDatatype value = (IPrimitiveDatatype) theValue; + if (value instanceof IntegerDt) { + theWriter.value(((IntegerDt) value).getValue()); + } else if (value instanceof DecimalDt) { + theWriter.value(((DecimalDt) value).getValue()); + } else if (value instanceof BooleanDt) { + theWriter.value(((BooleanDt) value).getValue()); + } else { + String valueStr = value.getValueAsString(); + theWriter.value(valueStr); + } + break; + } + case RESOURCE_BLOCK: + case COMPOSITE_DATATYPE: { + BaseRuntimeElementCompositeDefinition childCompositeDef = (BaseRuntimeElementCompositeDefinition) theChildDef; + theWriter.beginObject(); + encodeCompositeElementToStreamWriter(theValue, theWriter, childCompositeDef); + theWriter.endObject(); + break; + } + case RESOURCE_REF: { + ResourceReferenceDt value = (ResourceReferenceDt) theValue; + theWriter.beginObject(); + if (value.getReference().isEmpty()==false) { + theWriter.name("resource"); + theWriter.value(value.getReference().getValueAsString()); + } + if (value.getDisplay().isEmpty() == false) { + theWriter.name("display"); + theWriter.value(value.getDisplay().getValueAsString()); + } + theWriter.endObject(); + break; + } + case PRIMITIVE_XHTML: { + XhtmlDt dt = (XhtmlDt) theValue; + theWriter.value(dt.getValueAsString()); + break; + } + case UNDECL_EXT: + default: + throw new IllegalStateException("Should not have this state here: "+theChildDef.getChildType().name()); + } + + } + + @Override + public String encodeResourceToString(IResource theResource) throws DataFormatException, IOException { + Writer stringWriter = new StringWriter(); + encodeResourceToWriter(theResource, stringWriter); + return stringWriter.toString(); + } + + @Override + public void encodeResourceToWriter(IResource theResource, Writer theWriter) throws IOException { + JsonWriter eventWriter = new JsonWriter(theWriter); + eventWriter.setIndent(" "); + // try { + encodeResourceToJsonStreamWriter(theResource, eventWriter); + eventWriter.flush(); + // } catch (XMLStreamException e) { + // throw new + // ConfigurationException("Failed to initialize STaX event factory", e); + // } + } + + private void encodeResourceToJsonStreamWriter(IResource theResource, JsonWriter theEventWriter) throws IOException { + RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource); + + theEventWriter.beginObject(); + + theEventWriter.name("resourceType"); + theEventWriter.value(resDef.getName()); + + encodeCompositeElementToStreamWriter(theResource, theEventWriter, resDef); + + theEventWriter.endObject(); + } + + @Override + public Bundle parseBundle(Reader theReader) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle parseBundle(String theMessageString) throws ConfigurationException, DataFormatException { + // TODO Auto-generated method stub + return null; + } + + @Override + public IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException { + // TODO Auto-generated method stub + return null; + } + + @Override + public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T parseResource(Class theResourceType, String theMessageString) { + // TODO Auto-generated method stub + return null; + } + + @Override + public IResource parseResource(Class theResourceType, Reader theReader) { + // TODO Auto-generated method stub + return null; + } + +} 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 8256132b0b9..bfdd7595238 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 @@ -1,7 +1,6 @@ package ca.uhn.fhir.parser; -import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.*; import java.io.Reader; import java.io.StringReader; @@ -43,7 +42,6 @@ import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.IPrimitiveDatatype; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions; -import ca.uhn.fhir.model.api.BaseResourceReference; import ca.uhn.fhir.model.api.UndeclaredExtension; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; import ca.uhn.fhir.model.primitive.InstantDt; @@ -149,11 +147,6 @@ public class XmlParser implements IParser { } } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#encodeBundleToString(ca.uhn.fhir.model.api.Bundle) - */ @Override public String encodeBundleToString(Bundle theBundle) throws DataFormatException { StringWriter stringWriter = new StringWriter(); @@ -162,11 +155,6 @@ public class XmlParser implements IParser { return stringWriter.toString(); } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#encodeBundleToWriter(ca.uhn.fhir.model.api.Bundle, java.io.Writer) - */ @Override public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) { try { @@ -366,11 +354,7 @@ public class XmlParser implements IParser { } } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#encodeResourceToString(ca.uhn.fhir.model.api.IResource) - */ + @Override public String encodeResourceToString(IResource theResource) throws DataFormatException { Writer stringWriter = new StringWriter(); @@ -378,11 +362,6 @@ public class XmlParser implements IParser { return stringWriter.toString(); } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#encodeResourceToWriter(ca.uhn.fhir.model.api.IResource, java.io.Writer) - */ @Override public void encodeResourceToWriter(IResource theResource, Writer stringWriter) { XMLStreamWriter eventWriter; @@ -397,13 +376,8 @@ public class XmlParser implements IParser { } } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#encodeResourceToXmlStreamWriter(ca.uhn.fhir.model.api.IResource, javax.xml.stream.XMLStreamWriter) - */ - @Override - public void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException { + + private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException { RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource); eventWriter.writeStartElement(resDef.getName()); eventWriter.writeDefaultNamespace(FHIR_NS); @@ -520,13 +494,7 @@ public class XmlParser implements IParser { return parseResource(null, theMessageString); } - /* - * (non-Javadoc) - * - * @see ca.uhn.fhir.parser.IParser#parseResource(javax.xml.stream.XMLEventReader) - */ - @Override - public IResource parseResource(XMLEventReader theStreamReader) { + private IResource parseResource(XMLEventReader theStreamReader) { return parseResource(null, theStreamReader); } diff --git a/hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java b/hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java index 52fd378f365..bee810214bf 100644 --- a/hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java +++ b/hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java @@ -1,5 +1,7 @@ package example; +import java.io.IOException; + import ca.uhn.fhir.model.dstu.composite.HumanNameDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.resource.Observation; @@ -7,6 +9,7 @@ import ca.uhn.fhir.model.dstu.resource.Patient; import ca.uhn.fhir.model.dstu.valueset.NameUseEnum; import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.context.FhirContext; @@ -33,7 +36,7 @@ Patient patient = new Patient(); } - public void encodeMsg() { + public void encodeMsg() throws DataFormatException, IOException { FhirContext ctx = new FhirContext(Patient.class, Observation.class); //START SNIPPET: encodeMsg diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/RuntimeResourceDefinitionTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/RuntimeResourceDefinitionTest.java index 448070da237..168345aeca2 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/RuntimeResourceDefinitionTest.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/context/RuntimeResourceDefinitionTest.java @@ -2,6 +2,8 @@ package ca.uhn.fhir.context; import static org.junit.Assert.*; +import java.io.IOException; + import org.junit.Test; import ca.uhn.fhir.model.dstu.resource.Patient; @@ -9,12 +11,13 @@ import ca.uhn.fhir.model.dstu.resource.Profile; import ca.uhn.fhir.model.dstu.resource.Profile.ExtensionDefn; import ca.uhn.fhir.model.dstu.resource.Profile.Structure; import ca.uhn.fhir.model.dstu.valueset.DataTypeEnum; +import ca.uhn.fhir.parser.DataFormatException; public class RuntimeResourceDefinitionTest { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RuntimeResourceDefinitionTest.class); @Test - public void testToProfileStandard() { + public void testToProfileStandard() throws Exception { FhirContext ctx = new FhirContext(Patient.class, Profile.class); RuntimeResourceDefinition def = ctx.getResourceDefinition(Patient.class); @@ -33,7 +36,7 @@ public class RuntimeResourceDefinitionTest { } @Test - public void testToProfileExtensions() { + public void testToProfileExtensions() throws Exception { FhirContext ctx = new FhirContext(ResourceWithExtensionsA.class, Profile.class); RuntimeResourceDefinition def = ctx.getResourceDefinition(ResourceWithExtensionsA.class); 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 new file mode 100644 index 00000000000..a54d6ce5883 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java @@ -0,0 +1,27 @@ +package ca.uhn.fhir.parser; + +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.dstu.resource.Observation; +import ca.uhn.fhir.model.dstu.resource.Patient; + +public class JsonParserTest { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class); + + @Test + public void testSimpleEncode() throws IOException { + + FhirContext ctx = new FhirContext(Observation.class); +// String name = "/observation-example-eeg.xml"; + String name = "/example-patient-general.xml"; + Patient obs = ctx.newXmlParser().parseResource(Patient.class, IOUtils.toString(JsonParser.class.getResourceAsStream(name))); + String encoded = ctx.newJsonParser().encodeResourceToString(obs); + + 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 974fcbdec98..42c279d9e83 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 @@ -145,6 +145,29 @@ public class XmlParserTest { } + + @Test + public void testMessageWithMultipleTypes() throws SAXException, IOException { + + //@formatter:off + String msg = "" + + "" + + ""; + //@formatter:on + + FhirContext ctx = new FhirContext(Patient.class, ca.uhn.fhir.testmodel.Patient.class); + Patient patient1 = ctx.newXmlParser().parseResource(Patient.class, msg); + String encoded1 = ctx.newXmlParser().encodeResourceToString(patient1); + + ca.uhn.fhir.testmodel.Patient patient2 = ctx.newXmlParser().parseResource(ca.uhn.fhir.testmodel.Patient.class, msg); + String encoded2 = ctx.newXmlParser().encodeResourceToString(patient2); + + Diff d = new Diff(new StringReader(encoded1), new StringReader(encoded2)); + assertTrue(d.toString(), d.identical()); + + } + + @Test public void testLoadAndEncodeDeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException { FhirContext ctx = new FhirContext(ResourceWithExtensionsA.class); diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/Tester.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/Tester.java index 2c118a5121b..499a329d793 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/Tester.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/Tester.java @@ -1,15 +1,18 @@ package ca.uhn.fhir.rest.client; +import java.io.IOException; + import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.resource.Patient; import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException; public class Tester { - public static final void main(String[] args) { + public static final void main(String[] args) throws DataFormatException, IOException { try { FhirContext ctx = new FhirContext(Patient.class); diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/IdentifierDt.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/IdentifierDt.java new file mode 100644 index 00000000000..e7b08c77624 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/IdentifierDt.java @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + +package ca.uhn.fhir.testmodel; + +import ca.uhn.fhir.model.api.BaseElement; +import ca.uhn.fhir.model.api.ICompositeDatatype; +import ca.uhn.fhir.model.api.IQueryParameterType; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.dstu.composite.PeriodDt; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu.resource.Organization; +import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum; +import ca.uhn.fhir.model.primitive.BoundCodeDt; +import ca.uhn.fhir.model.primitive.CodeDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.model.primitive.UriDt; + +/** + * HAPI/FHIR Identifier Datatype + * (An identifier intended for computation) + * + *

+ * Definition: + * A technical identifier - identifies some entity uniquely and unambiguously + *

+ * + *

+ * Requirements: + * Need to be able to identify things with confidence and be sure that the identification is not subject to misinterpretation + *

+ */ +@DatatypeDef(name="Identifier") +public class IdentifierDt + extends BaseElement implements ICompositeDatatype , IQueryParameterType { + + /** + * Creates a new identifier + */ + public IdentifierDt() { + // nothing + } + + /** + * Creates a new identifier with the given system and value + */ + public IdentifierDt(String theSystem, String theValue) { + setSystem(theSystem); + setValue(theValue); + } + + @Child(name="use", type=CodeDt.class, order=0, min=0, max=1) + @Description( + shortDefinition="usual | official | temp | secondary (If known)", + formalDefinition="The purpose of this identifier" + ) + private BoundCodeDt myUse; + + @Child(name="label", type=StringDt.class, order=1, min=0, max=1) + @Description( + shortDefinition="Description of identifier", + formalDefinition="A text string for the identifier that can be displayed to a human so they can recognize the identifier" + ) + private StringDt myLabel; + + @Child(name="system", type=UriDt.class, order=2, min=0, max=1) + @Description( + shortDefinition="The namespace for the identifier", + formalDefinition="Establishes the namespace in which set of possible id values is unique." + ) + private UriDt mySystem; + + @Child(name="value", type=StringDt.class, order=3, min=0, max=1) + @Description( + shortDefinition="The value that is unique", + formalDefinition="The portion of the identifier typically displayed to the user and which is unique within the context of the system." + ) + private StringDt myValue; + + @Child(name="period", type=PeriodDt.class, order=4, min=0, max=1) + @Description( + shortDefinition="Time period when id is/was valid for use", + formalDefinition="Time period during which identifier is/was valid for use" + ) + private PeriodDt myPeriod; + + @Child(name="assigner", order=5, min=0, max=1, type={ + Organization.class, + }) + @Description( + shortDefinition="Organization that issued id (may be just text)", + formalDefinition="Organization that issued/manages the identifier" + ) + private ResourceReferenceDt myAssigner; + + + @Override + public boolean isEmpty() { + return super.isBaseEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty( myUse, myLabel, mySystem, myValue, myPeriod, myAssigner); + } + + /** + * Gets the value(s) for use (usual | official | temp | secondary (If known)). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * The purpose of this identifier + *

+ */ + public BoundCodeDt getUse() { + if (myUse == null) { + myUse = new BoundCodeDt(IdentifierUseEnum.VALUESET_BINDER); + } + return myUse; + } + + /** + * Sets the value(s) for use (usual | official | temp | secondary (If known)) + * + *

+ * Definition: + * The purpose of this identifier + *

+ */ + public void setUse(BoundCodeDt theValue) { + myUse = theValue; + } + + + /** + * Sets the value(s) for use (usual | official | temp | secondary (If known)) + * + *

+ * Definition: + * The purpose of this identifier + *

+ */ + public void setUse(IdentifierUseEnum theValue) { + getUse().setValueAsEnum(theValue); + } + + + /** + * Gets the value(s) for label (Description of identifier). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * A text string for the identifier that can be displayed to a human so they can recognize the identifier + *

+ */ + public StringDt getLabel() { + if (myLabel == null) { + myLabel = new StringDt(); + } + return myLabel; + } + + /** + * Sets the value(s) for label (Description of identifier) + * + *

+ * Definition: + * A text string for the identifier that can be displayed to a human so they can recognize the identifier + *

+ */ + public void setLabel(StringDt theValue) { + myLabel = theValue; + } + + + /** + * Sets the value for label (Description of identifier) + * + *

+ * Definition: + * A text string for the identifier that can be displayed to a human so they can recognize the identifier + *

+ */ + public void setLabel( String theString) { + myLabel = new StringDt(theString); + } + + + /** + * Gets the value(s) for system (The namespace for the identifier). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * Establishes the namespace in which set of possible id values is unique. + *

+ */ + public UriDt getSystem() { + if (mySystem == null) { + mySystem = new UriDt(); + } + return mySystem; + } + + /** + * Sets the value(s) for system (The namespace for the identifier) + * + *

+ * Definition: + * Establishes the namespace in which set of possible id values is unique. + *

+ */ + public void setSystem(UriDt theValue) { + mySystem = theValue; + } + + + /** + * Sets the value for system (The namespace for the identifier) + * + *

+ * Definition: + * Establishes the namespace in which set of possible id values is unique. + *

+ */ + public void setSystem( String theUri) { + mySystem = new UriDt(theUri); + } + + + /** + * Gets the value(s) for value (The value that is unique). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * The portion of the identifier typically displayed to the user and which is unique within the context of the system. + *

+ */ + public StringDt getValue() { + if (myValue == null) { + myValue = new StringDt(); + } + return myValue; + } + + /** + * Sets the value(s) for value (The value that is unique) + * + *

+ * Definition: + * The portion of the identifier typically displayed to the user and which is unique within the context of the system. + *

+ */ + public void setValue(StringDt theValue) { + myValue = theValue; + } + + + /** + * Sets the value for value (The value that is unique) + * + *

+ * Definition: + * The portion of the identifier typically displayed to the user and which is unique within the context of the system. + *

+ */ + public void setValue( String theString) { + myValue = new StringDt(theString); + } + + + /** + * Gets the value(s) for period (Time period when id is/was valid for use). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * Time period during which identifier is/was valid for use + *

+ */ + public PeriodDt getPeriod() { + if (myPeriod == null) { + myPeriod = new PeriodDt(); + } + return myPeriod; + } + + /** + * Sets the value(s) for period (Time period when id is/was valid for use) + * + *

+ * Definition: + * Time period during which identifier is/was valid for use + *

+ */ + public void setPeriod(PeriodDt theValue) { + myPeriod = theValue; + } + + + + /** + * Gets the value(s) for assigner (Organization that issued id (may be just text)). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * Organization that issued/manages the identifier + *

+ */ + public ResourceReferenceDt getAssigner() { + if (myAssigner == null) { + myAssigner = new ResourceReferenceDt(); + } + return myAssigner; + } + + /** + * Sets the value(s) for assigner (Organization that issued id (may be just text)) + * + *

+ * Definition: + * Organization that issued/manages the identifier + *

+ */ + public void setAssigner(ResourceReferenceDt theValue) { + myAssigner = theValue; + } + + + + + /** + * Returns true if this identifier has the same {@link IdentifierDt#getValue() value} + * and {@link IdentifierDt#getSystem() system} (as compared by simple equals comparison). + * Does not compare other values (e.g. {@link IdentifierDt#getUse() use}) or any extensions. + */ + public boolean matchesSystemAndValue(IdentifierDt theIdentifier) { + if (theIdentifier == null) { + return false; + } + return getValue().equals(theIdentifier.getValue()) && getSystem().equals(theIdentifier.getSystem()); + } + + /** + * {@inheritDoc} + */ + @Override + public String getValueAsQueryToken() { + if (org.apache.commons.lang3.StringUtils.isNotBlank(getSystem().getValueAsString())) { + return getSystem().getValueAsString() + '|' + getValue().getValueAsString(); + } else { + return getValue().getValueAsString(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setValueAsQueryToken(String theParameter) { + int barIndex = theParameter.indexOf('|'); + if (barIndex != -1) { + setSystem(new UriDt(theParameter.substring(0, barIndex))); + setValue(theParameter.substring(barIndex + 1)); + } else { + setValue(theParameter); + } + } + + +} \ No newline at end of file diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/Patient.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/Patient.java new file mode 100644 index 00000000000..f2f557c0711 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/testmodel/Patient.java @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + +package ca.uhn.fhir.testmodel; + +import java.util.*; +import ca.uhn.fhir.model.api.*; +import ca.uhn.fhir.model.api.annotation.*; + +/** + * HAPI/FHIR Patient Resource + * (Information about a person or animal receiving health care services) + * + *

+ * Definition: + * Demographics and other administrative information about a person or animal receiving care or other health-related services + *

+ * + *

+ * Requirements: + * Tracking patient is the center of the healthcare process + *

+ */ +@ResourceDef(name="Patient", profile="http://hl7.org/fhir/profiles/Patient") +public class Patient extends BaseResource implements IResource { + + + @Child(name="identifier", type=IdentifierDt.class, order=0, min=0, max=Child.MAX_UNLIMITED) + @Description( + shortDefinition="An identifier for the person as this patient", + formalDefinition="An identifier that applies to this person as a patient" + ) + private List myIdentifier; + + + @Override + public boolean isEmpty() { + return super.isBaseEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty( myIdentifier); + } + + /** + * Gets the value(s) for identifier (An identifier for the person as this patient). + * creating it if it does + * not exist. Will not return null. + * + *

+ * Definition: + * An identifier that applies to this person as a patient + *

+ */ + public List getIdentifier() { + if (myIdentifier == null) { + myIdentifier = new ArrayList(); + } + return myIdentifier; + } + + /** + * Sets the value(s) for identifier (An identifier for the person as this patient) + * + *

+ * Definition: + * An identifier that applies to this person as a patient + *

+ */ + public void setIdentifier(List theValue) { + myIdentifier = theValue; + } + + /** + * Adds and returns a new value for identifier (An identifier for the person as this patient) + * + *

+ * Definition: + * An identifier that applies to this person as a patient + *

+ */ + public IdentifierDt addIdentifier() { + IdentifierDt newType = new IdentifierDt(); + getIdentifier().add(newType); + return newType; + } + + + + + +} \ No newline at end of file diff --git a/hapi-fhir-base/src/test/resources/example-patient-general.xml b/hapi-fhir-base/src/test/resources/example-patient-general.xml new file mode 100644 index 00000000000..b3a96adaac2 --- /dev/null +++ b/hapi-fhir-base/src/test/resources/example-patient-general.xml @@ -0,0 +1,114 @@ + + + +
+ + + + + + + + + + + + + + + + + + + +
NamePeter James Chalmers ("Jim")
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/hapi-fhir-base/src/test/resources/observation-example-eeg.xml b/hapi-fhir-base/src/test/resources/observation-example-eeg.xml index f643b57d38f..30a3c0fad3a 100644 --- a/hapi-fhir-base/src/test/resources/observation-example-eeg.xml +++ b/hapi-fhir-base/src/test/resources/observation-example-eeg.xml @@ -2,7 +2,6 @@ - -