Merge branch 'master' of github.com:jamesagnew/hapi-fhir
This commit is contained in:
commit
dfbfed2d35
|
@ -74,30 +74,30 @@ public class GenericClientExample {
|
||||||
// END SNIPPET: create
|
// END SNIPPET: create
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
// START SNIPPET: createConditional
|
// START SNIPPET: createConditional
|
||||||
// One form
|
// One form
|
||||||
MethodOutcome outcome = client.create()
|
MethodOutcome outcome = client.create()
|
||||||
.resource(patient)
|
.resource(patient)
|
||||||
.conditionalByUrl("Patient?identifier=system%7C00001")
|
.conditionalByUrl("Patient?identifier=system%7C00001")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
// Another form
|
// Another form
|
||||||
MethodOutcome outcome2 = client.create()
|
MethodOutcome outcome2 = client.create()
|
||||||
.resource(patient)
|
.resource(patient)
|
||||||
.conditional()
|
.conditional()
|
||||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
// This will return true if the server responded with an HTTP 201 created,
|
// This will return true if the server responded with an HTTP 201 created,
|
||||||
// otherwise it will return null.
|
// otherwise it will return null.
|
||||||
Boolean created = outcome.getCreated();
|
Boolean created = outcome.getCreated();
|
||||||
|
|
||||||
// The ID of the created, or the pre-existing resource
|
// The ID of the created, or the pre-existing resource
|
||||||
IdDt id = outcome.getId();
|
IdDt id = outcome.getId();
|
||||||
// END SNIPPET: createConditional
|
// END SNIPPET: createConditional
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: update
|
// START SNIPPET: update
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
// ..populate the patient object..
|
// ..populate the patient object..
|
||||||
|
@ -125,21 +125,21 @@ public class GenericClientExample {
|
||||||
// END SNIPPET: update
|
// END SNIPPET: update
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
// START SNIPPET: updateConditional
|
// START SNIPPET: updateConditional
|
||||||
client.update()
|
client.update()
|
||||||
.resource(patient)
|
.resource(patient)
|
||||||
.conditionalByUrl("Patient?identifier=system%7C00001")
|
.conditionalByUrl("Patient?identifier=system%7C00001")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
client.update()
|
client.update()
|
||||||
.resource(patient)
|
.resource(patient)
|
||||||
.conditional()
|
.conditional()
|
||||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: updateConditional
|
// END SNIPPET: updateConditional
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: etagupdate
|
// START SNIPPET: etagupdate
|
||||||
// First, let's retrive the latest version of a resource
|
// First, let's retrive the latest version of a resource
|
||||||
// from the server
|
// from the server
|
||||||
|
@ -176,26 +176,26 @@ public class GenericClientExample {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: delete
|
// START SNIPPET: delete
|
||||||
BaseOperationOutcome resp = client.delete().resourceById(new IdDt("Patient", "1234")).execute();
|
BaseOperationOutcome resp = client.delete().resourceById(new IdDt("Patient", "1234")).execute();
|
||||||
|
|
||||||
// outcome may be null if the server didn't return one
|
// outcome may be null if the server didn't return one
|
||||||
if (resp != null) {
|
if (resp != null) {
|
||||||
OperationOutcome outcome = (OperationOutcome) resp;
|
OperationOutcome outcome = (OperationOutcome) resp;
|
||||||
System.out.println(outcome.getIssueFirstRep().getDetailsElement().getValue());
|
System.out.println(outcome.getIssueFirstRep().getDetailsElement().getValue());
|
||||||
}
|
}
|
||||||
// END SNIPPET: delete
|
// END SNIPPET: delete
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: deleteConditional
|
// START SNIPPET: deleteConditional
|
||||||
client.delete()
|
client.delete()
|
||||||
.resourceConditionalByUrl("Patient?identifier=system%7C00001")
|
.resourceConditionalByUrl("Patient?identifier=system%7C00001")
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
client.delete()
|
client.delete()
|
||||||
.resourceConditionalByType("Patient")
|
.resourceConditionalByType("Patient")
|
||||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("system", "00001"))
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: deleteConditional
|
// END SNIPPET: deleteConditional
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: search
|
// START SNIPPET: search
|
||||||
|
|
|
@ -49,13 +49,14 @@ import javax.json.stream.JsonGenerator;
|
||||||
import javax.json.stream.JsonGeneratorFactory;
|
import javax.json.stream.JsonGeneratorFactory;
|
||||||
import javax.json.stream.JsonParsingException;
|
import javax.json.stream.JsonParsingException;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.IBase;
|
import org.hl7.fhir.instance.model.IBase;
|
||||||
import org.hl7.fhir.instance.model.IBaseResource;
|
import org.hl7.fhir.instance.model.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
|
||||||
|
@ -88,13 +89,12 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.api.Tag;
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
|
||||||
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
|
import ca.uhn.fhir.model.base.resource.BaseBinary;
|
||||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||||
|
@ -102,10 +102,6 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is the FHIR JSON parser/encoder. Users should not interact with this
|
|
||||||
* class directly, but should use {@link FhirContext#newJsonParser()} to get an instance.
|
|
||||||
*/
|
|
||||||
public class JsonParser extends BaseParser implements IParser {
|
public class JsonParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1;
|
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1;
|
||||||
|
@ -302,9 +298,9 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
// IResource nextResource = nextEntry.getResource();
|
// IResource nextResource = nextEntry.getResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextEntry.getTransactionMethod().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
||||||
theEventWriter.writeStartObject("transaction");
|
theEventWriter.writeStartObject("transaction");
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "method", nextEntry.getTransactionMethod().getValue());
|
writeOptionalTagWithTextNode(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue());
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
|
writeOptionalTagWithTextNode(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
|
||||||
theEventWriter.writeEnd();
|
theEventWriter.writeEnd();
|
||||||
}
|
}
|
||||||
|
@ -456,7 +452,7 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
case RESOURCE:
|
case RESOURCE:
|
||||||
IBaseResource resource = (IBaseResource) theNextValue;
|
IBaseResource resource = (IBaseResource) theNextValue;
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(resource);
|
||||||
encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, false);
|
encodeResourceToJsonStreamWriter(def, resource, theWriter, theChildName, true);
|
||||||
break;
|
break;
|
||||||
case UNDECL_EXT:
|
case UNDECL_EXT:
|
||||||
default:
|
default:
|
||||||
|
@ -631,12 +627,12 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||||
boolean theContainedResource) throws IOException {
|
boolean theIsSubElementWithinResource) throws IOException {
|
||||||
String resourceId = null;
|
String resourceId = null;
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
IResource res = (IResource) theResource;
|
IResource res = (IResource) theResource;
|
||||||
if (StringUtils.isNotBlank(res.getId().getIdPart())) {
|
if (StringUtils.isNotBlank(res.getId().getIdPart())) {
|
||||||
if (theContainedResource) {
|
if (theIsSubElementWithinResource) {
|
||||||
resourceId = res.getId().getIdPart();
|
resourceId = res.getId().getIdPart();
|
||||||
} else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
} else if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||||
resourceId = res.getId().getIdPart();
|
resourceId = res.getId().getIdPart();
|
||||||
|
@ -644,17 +640,17 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
} else if (theResource instanceof IAnyResource) {
|
} else if (theResource instanceof IAnyResource) {
|
||||||
IAnyResource res = (IAnyResource) theResource;
|
IAnyResource res = (IAnyResource) theResource;
|
||||||
if (theContainedResource && StringUtils.isNotBlank(res.getId())) {
|
if (theIsSubElementWithinResource && StringUtils.isNotBlank(res.getId())) {
|
||||||
resourceId = res.getId();
|
resourceId = res.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);
|
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theIsSubElementWithinResource, resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
|
||||||
boolean theContainedResource, String theResourceId) throws IOException {
|
boolean theIsSubElementWithinResource, String theResourceId) throws IOException {
|
||||||
if (!theContainedResource) {
|
if (!theIsSubElementWithinResource) {
|
||||||
super.containResourcesForEncoding(theResource);
|
super.containResourcesForEncoding(theResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,64 +669,55 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) {
|
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) {
|
||||||
IResource resource = (IResource) theResource;
|
IResource resource = (IResource) theResource;
|
||||||
|
//Object securityLabelRawObj =
|
||||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||||
IdDt resourceId = resource.getId();
|
if (!ElementUtil.isEmpty(resource.getId().getVersionIdPart(), ResourceMetadataKeyEnum.UPDATED.get(resource))
|
||||||
String versionIdPart = resourceId.getVersionIdPart();
|
|| (securityLabels != null && !securityLabels.isEmpty())) {
|
||||||
if (isBlank(versionIdPart)) {
|
|
||||||
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
|
||||||
}
|
|
||||||
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
|
||||||
List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
|
||||||
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(resource);
|
|
||||||
if (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, profiles) == false) {
|
|
||||||
theEventWriter.writeStartObject("meta");
|
theEventWriter.writeStartObject("meta");
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart());
|
writeOptionalTagWithTextNode(theEventWriter, "versionId", resource.getId().getVersionIdPart());
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource));
|
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", ResourceMetadataKeyEnum.UPDATED.get(resource));
|
||||||
|
|
||||||
if (profiles != null && profiles.isEmpty()==false) {
|
|
||||||
theEventWriter.writeStartArray("profile");
|
|
||||||
for (IdDt profile : profiles) {
|
|
||||||
if (profile != null && isNotBlank(profile.getValue())) {
|
|
||||||
theEventWriter.write(profile.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
theEventWriter.writeEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (securityLabels.isEmpty()==false) {
|
if (securityLabels != null) {
|
||||||
theEventWriter.writeStartArray("security");
|
if (!securityLabels.isEmpty()) {
|
||||||
for (BaseCodingDt securityLabel : securityLabels) {
|
theEventWriter.writeStartArray("security");
|
||||||
theEventWriter.writeStartObject();
|
|
||||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
for (BaseCodingDt securityLabel : securityLabels) {
|
||||||
encodeCompositeElementChildrenToStreamWriter(resDef, resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
|
theEventWriter.writeStartObject();
|
||||||
theEventWriter.writeEnd();
|
|
||||||
|
UriDt system = securityLabel.getSystemElement();
|
||||||
|
if (system != null && !system.isEmpty())
|
||||||
|
writeOptionalTagWithTextNode(theEventWriter, "system", system.getValueAsString());
|
||||||
|
|
||||||
|
CodeDt code = securityLabel.getCodeElement();
|
||||||
|
|
||||||
|
if (code != null && !code.isEmpty())
|
||||||
|
writeOptionalTagWithTextNode(theEventWriter, "code", code.getValueAsString());
|
||||||
|
|
||||||
|
StringDt display = securityLabel.getDisplayElement();
|
||||||
|
if (display != null && !display.isEmpty())
|
||||||
|
writeOptionalTagWithTextNode(theEventWriter, "display", display.getValueAsString());
|
||||||
|
|
||||||
|
/*todo: handle version
|
||||||
|
StringDt version = securityLabel.getVersion();
|
||||||
|
if (version != null && ! version.isEmpty())
|
||||||
|
writeOptionalTagWithTextNode(theEventWriter, "version", version.getValueAsString());
|
||||||
|
*/
|
||||||
|
theEventWriter.writeEnd(); //end the individual security label
|
||||||
|
}
|
||||||
|
theEventWriter.writeEnd(); //end security labels array
|
||||||
}
|
}
|
||||||
theEventWriter.writeEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tags != null && tags.isEmpty()==false) {
|
|
||||||
theEventWriter.writeStartArray("tag");
|
|
||||||
for (Tag tag : tags) {
|
|
||||||
theEventWriter.writeStartObject();
|
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "system", tag.getScheme());
|
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "code", tag.getTerm());
|
|
||||||
writeOptionalTagWithTextNode(theEventWriter, "display", tag.getLabel());
|
|
||||||
theEventWriter.writeEnd();
|
|
||||||
}
|
|
||||||
theEventWriter.writeEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.writeEnd(); //end meta
|
theEventWriter.writeEnd(); //end meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theResource instanceof IBaseBinary) {
|
if (theResource instanceof BaseBinary) {
|
||||||
IBaseBinary bin = (IBaseBinary) theResource;
|
BaseBinary bin = (BaseBinary) theResource;
|
||||||
theEventWriter.write("contentType", bin.getContentType());
|
theEventWriter.write("contentType", bin.getContentType());
|
||||||
theEventWriter.write("content", bin.getContentAsBase64());
|
theEventWriter.write("content", bin.getContentAsBase64());
|
||||||
} else {
|
} else {
|
||||||
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
|
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef, theIsSubElementWithinResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
theEventWriter.writeEnd();
|
theEventWriter.writeEnd();
|
||||||
|
|
|
@ -1674,7 +1674,7 @@ class ParserState<T> {
|
||||||
|
|
||||||
private class SecurityLabelElementStateHapi extends ElementCompositeState {
|
private class SecurityLabelElementStateHapi extends ElementCompositeState {
|
||||||
|
|
||||||
public SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState,BaseRuntimeElementCompositeDefinition<?> theDef, BaseCodingDt codingDt) {
|
public SecurityLabelElementStateHapi(ParserState<T>.PreResourceState thePreResourceState, BaseRuntimeElementCompositeDefinition<?> theDef, BaseCodingDt codingDt) {
|
||||||
super(thePreResourceState, theDef, codingDt);
|
super(thePreResourceState, theDef, codingDt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1716,7 +1716,7 @@ class ParserState<T> {
|
||||||
securityLabels = new ArrayList<BaseCodingDt>();
|
securityLabels = new ArrayList<BaseCodingDt>();
|
||||||
myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels);
|
myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels);
|
||||||
}
|
}
|
||||||
BaseCodingDt securityLabel= myContext.getVersion().newCodingDt();
|
BaseCodingDt securityLabel = myContext.getVersion().newCodingDt();
|
||||||
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
BaseRuntimeElementCompositeDefinition<?> codinfDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
||||||
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
|
push(new SecurityLabelElementStateHapi(getPreResourceState(), codinfDef, securityLabel));
|
||||||
securityLabels.add(securityLabel);
|
securityLabels.add(securityLabel);
|
||||||
|
|
|
@ -20,17 +20,17 @@ package ca.uhn.fhir.parser;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
import static org.apache.commons.lang3.StringUtils.*;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import javax.xml.stream.FactoryConfigurationError;
|
import javax.xml.stream.FactoryConfigurationError;
|
||||||
|
@ -46,12 +46,13 @@ import javax.xml.stream.events.Namespace;
|
||||||
import javax.xml.stream.events.StartElement;
|
import javax.xml.stream.events.StartElement;
|
||||||
import javax.xml.stream.events.XMLEvent;
|
import javax.xml.stream.events.XMLEvent;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.instance.model.IBase;
|
import org.hl7.fhir.instance.model.IBase;
|
||||||
import org.hl7.fhir.instance.model.IBaseResource;
|
import org.hl7.fhir.instance.model.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||||
|
@ -72,32 +73,25 @@ import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.BundleEntry;
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
|
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.IResource;
|
||||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.api.Tag;
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
|
||||||
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.base.resource.BaseBinary;
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
|
||||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
|
||||||
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
|
import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
|
||||||
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
||||||
import ca.uhn.fhir.util.XmlUtil;
|
import ca.uhn.fhir.util.XmlUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is the FHIR XML parser/encoder. Users should not interact with this
|
|
||||||
* class directly, but should use {@link FhirContext#newXmlParser()} to get an instance.
|
|
||||||
*/
|
|
||||||
public class XmlParser extends BaseParser implements IParser {
|
public class XmlParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
||||||
static final String FHIR_NS = "http://hl7.org/fhir";
|
static final String FHIR_NS = "http://hl7.org/fhir";
|
||||||
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
||||||
|
@ -251,12 +245,12 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
|
writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
|
||||||
writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());
|
writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());
|
||||||
|
|
||||||
writeAtomLink(eventWriter, Constants.LINK_SELF, theBundle.getLinkSelf());
|
writeAtomLink(eventWriter, "self", theBundle.getLinkSelf());
|
||||||
writeAtomLink(eventWriter, Constants.LINK_FIRST, theBundle.getLinkFirst());
|
writeAtomLink(eventWriter, "first", theBundle.getLinkFirst());
|
||||||
writeAtomLink(eventWriter, Constants.LINK_PREVIOUS, theBundle.getLinkPrevious());
|
writeAtomLink(eventWriter, "previous", theBundle.getLinkPrevious());
|
||||||
writeAtomLink(eventWriter, Constants.LINK_NEXT, theBundle.getLinkNext());
|
writeAtomLink(eventWriter, "next", theBundle.getLinkNext());
|
||||||
writeAtomLink(eventWriter, Constants.LINK_LAST, theBundle.getLinkLast());
|
writeAtomLink(eventWriter, "last", theBundle.getLinkLast());
|
||||||
writeAtomLink(eventWriter, Constants.LINK_FHIR_BASE, theBundle.getLinkBase());
|
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase());
|
||||||
|
|
||||||
if (theBundle.getTotalResults().getValue() != null) {
|
if (theBundle.getTotalResults().getValue() != null) {
|
||||||
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
|
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
|
||||||
|
@ -418,9 +412,9 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
// IResource nextResource = nextEntry.getResource();
|
// IResource nextResource = nextEntry.getResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextEntry.getTransactionMethod().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
||||||
theEventWriter.writeStartElement("transaction");
|
theEventWriter.writeStartElement("transaction");
|
||||||
writeOptionalTagWithValue(theEventWriter, "method", nextEntry.getTransactionMethod().getValue());
|
writeOptionalTagWithValue(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue());
|
||||||
writeOptionalTagWithValue(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
|
writeOptionalTagWithValue(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
@ -442,7 +436,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef,
|
private void encodeChildElementToStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef,
|
||||||
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
String theExtensionUrl, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||||
if (nextValue.isEmpty()) {
|
if (nextValue.isEmpty()) {
|
||||||
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
|
if (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES && getContainedResources().isEmpty() == false && theIncludedResource == false) {
|
||||||
// We still want to go in..
|
// We still want to go in..
|
||||||
|
@ -521,12 +515,12 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children,
|
private void encodeCompositeElementChildrenToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children,
|
||||||
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||||
for (BaseRuntimeChildDefinition nextChild : children) {
|
for (BaseRuntimeChildDefinition nextChild : children) {
|
||||||
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
|
if (nextChild.getElementName().equals("extension") || nextChild.getElementName().equals("modifierExtension")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
|
if (nextChild instanceof RuntimeChildNarrativeDefinition && !theIncludedResource) {
|
||||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
|
@ -581,7 +575,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
// This is called for the Query resource in DSTU1 only
|
// This is called for the Query resource in DSTU1 only
|
||||||
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
|
extensionUrl = ((IBaseExtension<?>) nextValue).getUrl();
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
|
||||||
|
|
||||||
} else if (extensionUrl != null && childName.equals("extension") == false) {
|
} else if (extensionUrl != null && childName.equals("extension") == false) {
|
||||||
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
||||||
if (extDef.isModifier()) {
|
if (extDef.isModifier()) {
|
||||||
|
@ -603,7 +597,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition,
|
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> theElementDefinition,
|
||||||
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||||
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
|
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
|
||||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
|
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getExtensions(), theIncludedResource);
|
||||||
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
|
encodeCompositeElementChildrenToStreamWriter(theResource, theElement, theEventWriter, theElementDefinition.getChildren(), theIncludedResource);
|
||||||
|
@ -651,7 +645,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
|
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter,
|
||||||
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||||
/*
|
/*
|
||||||
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy way to make that happen, but hopefully this won't matter as much once we use the
|
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy way to make that happen, but hopefully this won't matter as much once we use the
|
||||||
* HL7 structures
|
* HL7 structures
|
||||||
|
@ -739,55 +733,69 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
// HL7.org Structures
|
// HL7.org Structures
|
||||||
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
|
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, resDef, theContainedResource);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||||
|
|
||||||
// DSTU2+
|
// DSTU2+
|
||||||
|
|
||||||
|
|
||||||
IResource resource = (IResource) theResource;
|
IResource resource = (IResource) theResource;
|
||||||
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
|
writeOptionalTagWithValue(theEventWriter, "id", theResourceId);
|
||||||
|
|
||||||
|
|
||||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||||
|
//Object securityLabelRawObj = resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||||
|
List<BaseCodingDt> securityLabels = (List<BaseCodingDt>) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||||
IdDt resourceId = resource.getId();
|
IdDt resourceId = resource.getId();
|
||||||
String versionIdPart = resourceId.getVersionIdPart();
|
if (resourceId != null && isNotBlank(resourceId.getVersionIdPart())
|
||||||
if (isBlank(versionIdPart)) {
|
|| (updated != null && !updated.isEmpty())
|
||||||
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
|| (securityLabels != null && !securityLabels.isEmpty())) {
|
||||||
}
|
|
||||||
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
|
||||||
List<IdDt> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
|
||||||
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(resource);
|
|
||||||
if (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, profiles) == false) {
|
|
||||||
theEventWriter.writeStartElement("meta");
|
theEventWriter.writeStartElement("meta");
|
||||||
|
String versionIdPart = resourceId.getVersionIdPart();
|
||||||
|
if (isBlank(versionIdPart)) {
|
||||||
|
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
|
||||||
|
}
|
||||||
writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
|
writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
|
||||||
}
|
}
|
||||||
for (IdDt profile : profiles) {
|
|
||||||
theEventWriter.writeStartElement("profile");
|
if (securityLabels != null) {
|
||||||
theEventWriter.writeAttribute("value", profile.getValue());
|
|
||||||
theEventWriter.writeEndElement();
|
if (!securityLabels.isEmpty()) {
|
||||||
}
|
|
||||||
for (BaseCodingDt securityLabel : securityLabels) {
|
for (BaseCodingDt securityLabel : securityLabels) {
|
||||||
theEventWriter.writeStartElement("security");
|
theEventWriter.writeStartElement("security");
|
||||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(securityLabel.getClass());
|
|
||||||
encodeCompositeElementChildrenToStreamWriter(resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
|
UriDt system = securityLabel.getSystemElement();
|
||||||
theEventWriter.writeEndElement();
|
if (system != null && !system.isEmpty())
|
||||||
}
|
writeOptionalTagWithValue(theEventWriter, "system", system.getValueAsString());
|
||||||
if (tags != null) {
|
|
||||||
for (Tag tag : tags) {
|
CodeDt code = securityLabel.getCodeElement();
|
||||||
theEventWriter.writeStartElement("tag");
|
if (code != null && !code.isEmpty())
|
||||||
writeOptionalTagWithValue(theEventWriter, "system", tag.getScheme());
|
writeOptionalTagWithValue(theEventWriter, "code", code.getValueAsString());
|
||||||
writeOptionalTagWithValue(theEventWriter, "code", tag.getTerm());
|
|
||||||
writeOptionalTagWithValue(theEventWriter, "display", tag.getLabel());
|
StringDt display = securityLabel.getDisplayElement();
|
||||||
theEventWriter.writeEndElement();
|
if (display != null && !display.isEmpty())
|
||||||
|
writeOptionalTagWithValue(theEventWriter, "display", display.getValueAsString());
|
||||||
|
|
||||||
|
/*todo: handle version
|
||||||
|
StringDt version = securityLabel.getVersion();
|
||||||
|
if (version != null && ! version.isEmpty())
|
||||||
|
writeOptionalTagWithValue(theEventWriter, "version", version.getValueAsString());
|
||||||
|
*/
|
||||||
|
theEventWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
theEventWriter.writeEndElement();
|
theEventWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theResource instanceof IBaseBinary) {
|
if (theResource instanceof BaseBinary) {
|
||||||
IBaseBinary bin = (IBaseBinary) theResource;
|
BaseBinary bin = (BaseBinary) theResource;
|
||||||
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
|
||||||
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
|
||||||
} else {
|
} else {
|
||||||
|
@ -801,8 +809,8 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
theEventWriter.writeAttribute("id", theResourceId);
|
theEventWriter.writeAttribute("id", theResourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theResource instanceof IBaseBinary) {
|
if (theResource instanceof BaseBinary) {
|
||||||
IBaseBinary bin = (IBaseBinary) theResource;
|
BaseBinary bin = (BaseBinary) theResource;
|
||||||
if (bin.getContentType() != null) {
|
if (bin.getContentType() != null) {
|
||||||
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
theEventWriter.writeAttribute("contentType", bin.getContentType());
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class MethodOutcome {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are
|
* This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are
|
||||||
* returned to client instances, if the server has responded with an HTTP 201 Created.
|
* returned to client instances, if the server has responded with an HTTP 201 Created.
|
||||||
*/
|
*/
|
||||||
public Boolean getCreated() {
|
public Boolean getCreated() {
|
||||||
|
|
|
@ -280,9 +280,9 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
||||||
} else {
|
} else {
|
||||||
retVal = parser.parseResource(requestReader);
|
retVal = parser.parseResource(requestReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
retVal.setId(theRequest.getId());
|
retVal.setId(theRequest.getId());
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,11 @@
|
||||||
</bean>
|
</bean>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||||
|
|
||||||
</beans>
|
</beans>
|
|
@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
|
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.web.context.ContextLoaderListener;
|
import org.springframework.web.context.ContextLoaderListener;
|
||||||
|
@ -167,10 +168,15 @@ public class TestRestfulServer extends RestfulServer {
|
||||||
* Do some fancy logging to create a nice access log that has details
|
* Do some fancy logging to create a nice access log that has details
|
||||||
* about each incoming request.
|
* about each incoming request.
|
||||||
*/
|
*/
|
||||||
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
|
List<IServerInterceptor> interceptorBeans = myAppCtx.getBean("myServerInterceptors", List.class);
|
||||||
|
for (IServerInterceptor interceptor : interceptorBeans)
|
||||||
|
this.registerInterceptor(interceptor);
|
||||||
|
|
||||||
|
/*LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
|
||||||
loggingInterceptor.setLoggerName("fhirtest.access");
|
loggingInterceptor.setLoggerName("fhirtest.access");
|
||||||
loggingInterceptor.setMessageFormat("Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]");
|
loggingInterceptor.setMessageFormat("Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]");
|
||||||
this.registerInterceptor(loggingInterceptor);
|
this.registerInterceptor(loggingInterceptor);
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,13 @@
|
||||||
</bean>
|
</bean>
|
||||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||||
|
|
||||||
|
<util:list id="myServerInterceptors">
|
||||||
|
<ref bean="myLoggingInterceptor"/>
|
||||||
|
</util:list>
|
||||||
|
<bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor">
|
||||||
|
<property name="loggerName" value="fhirtest.access"/>
|
||||||
|
<property name="messageFormat"
|
||||||
|
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
|
@ -131,7 +131,7 @@ public class GenericClientTest {
|
||||||
|
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[]{new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -140,14 +140,14 @@ public class GenericClientTest {
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
MethodOutcome resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute();
|
MethodOutcome resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute();
|
||||||
assertTrue(resp.getCreated());
|
assertTrue(resp.getCreated());
|
||||||
|
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute();
|
resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute();
|
||||||
assertNull(resp.getCreated());
|
assertNull(resp.getCreated());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithStringAutoDetectsEncoding() throws Exception {
|
public void testCreateWithStringAutoDetectsEncoding() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class FhirDstu2 implements IFhirVersion {
|
||||||
public Class<? extends BaseContainedDt> getContainedType() {
|
public Class<? extends BaseContainedDt> getContainedType() {
|
||||||
return ContainedDt.class;
|
return ContainedDt.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseCodingDt newCodingDt() {
|
public BaseCodingDt newCodingDt() {
|
||||||
return new CodingDt();
|
return new CodingDt();
|
||||||
|
|
|
@ -165,8 +165,10 @@
|
||||||
|
|
||||||
<h4>Search - Using HTTP POST</h4>
|
<h4>Search - Using HTTP POST</h4>
|
||||||
<p>
|
<p>
|
||||||
The FHIR specification allows the use of an HTTP POST to transmit a search to a server instead of using
|
The FHIR specification allows the use of an HTTP POST to transmit a search to a server instead of
|
||||||
an HTTP GET. With this style of search, the search parameters are included in the request body instead
|
using
|
||||||
|
an HTTP GET. With this style of search, the search parameters are included in the request body
|
||||||
|
instead
|
||||||
of the request URL, which can be useful if you need to transmit a search with a large number
|
of the request URL, which can be useful if you need to transmit a search with a large number
|
||||||
of parameters.
|
of parameters.
|
||||||
</p>
|
</p>
|
||||||
|
@ -176,7 +178,7 @@
|
||||||
case the client automatically switches to POST.
|
case the client automatically switches to POST.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
An alternate form of the search URL (using a URL ending with <code>_search</code>) was also
|
An alternate form of the search URL (using a URL ending with<code>_search</code>) was also
|
||||||
supported in FHIR DSTU1. This form is no longer valid in FHIR DSTU2, but HAPI retains support
|
supported in FHIR DSTU1. This form is no longer valid in FHIR DSTU2, but HAPI retains support
|
||||||
for using this form in order to interoperate with servers which use it.
|
for using this form in order to interoperate with servers which use it.
|
||||||
</p>
|
</p>
|
||||||
|
@ -211,18 +213,18 @@
|
||||||
<param name="file"
|
<param name="file"
|
||||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<h4>Conditional Creates</h4>
|
<h4>Conditional Creates</h4>
|
||||||
<p>
|
<p>
|
||||||
FHIR also specifies a type of update called "conditional create", where
|
FHIR also specifies a type of update called "conditional create", where
|
||||||
a set of search parameters are provided and a new resource is only
|
a set of search parameters are provided and a new resource is only
|
||||||
created if no existing resource matches those parameters. See the
|
created if no existing resource matches those parameters. See the
|
||||||
FHIR specification for more information on conditional creation.
|
FHIR specification for more information on conditional creation.
|
||||||
</p>
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="updateConditional" />
|
<param name="id" value="updateConditional"/>
|
||||||
<param name="file"
|
<param name="file"
|
||||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
value="examples/src/main/java/example/GenericClientExample.java"/>
|
||||||
</macro>
|
</macro>
|
||||||
</subsection>
|
</subsection>
|
||||||
|
|
||||||
|
@ -276,7 +278,7 @@
|
||||||
</macro>
|
</macro>
|
||||||
<h4>Conditional Deletes</h4>
|
<h4>Conditional Deletes</h4>
|
||||||
<p>
|
<p>
|
||||||
Conditional deletions are also possible, which is a form where
|
Conditional deletions are also possible, which is a form where
|
||||||
instead of deleting a resource using its logical ID, you specify
|
instead of deleting a resource using its logical ID, you specify
|
||||||
a set of search criteria and a single resource is deleted if
|
a set of search criteria and a single resource is deleted if
|
||||||
it matches that criteria. Note that this is not a mechanism
|
it matches that criteria. Note that this is not a mechanism
|
||||||
|
@ -284,9 +286,9 @@
|
||||||
on conditional deletes and how they are used.
|
on conditional deletes and how they are used.
|
||||||
</p>
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="deleteConditional" />
|
<param name="id" value="deleteConditional"/>
|
||||||
<param name="file"
|
<param name="file"
|
||||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
value="examples/src/main/java/example/GenericClientExample.java"/>
|
||||||
</macro>
|
</macro>
|
||||||
</subsection>
|
</subsection>
|
||||||
|
|
||||||
|
@ -305,19 +307,19 @@
|
||||||
<param name="file"
|
<param name="file"
|
||||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<h4>Conditional Updates</h4>
|
<h4>Conditional Updates</h4>
|
||||||
<p>
|
<p>
|
||||||
FHIR also specifies a type of update called "conditional updates", where
|
FHIR also specifies a type of update called "conditional updates", where
|
||||||
insetad of using the logical ID of a resource to update, a set of
|
insetad of using the logical ID of a resource to update, a set of
|
||||||
search parameters is provided. If a single resource matches that set of
|
search parameters is provided. If a single resource matches that set of
|
||||||
parameters, that resource is updated. See the FHIR specification for
|
parameters, that resource is updated. See the FHIR specification for
|
||||||
information on how conditional updates work.
|
information on how conditional updates work.
|
||||||
</p>
|
</p>
|
||||||
<macro name="snippet">
|
<macro name="snippet">
|
||||||
<param name="id" value="updateConditional" />
|
<param name="id" value="updateConditional"/>
|
||||||
<param name="file"
|
<param name="file"
|
||||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
value="examples/src/main/java/example/GenericClientExample.java"/>
|
||||||
</macro>
|
</macro>
|
||||||
|
|
||||||
<h4>ETags and Resource Contention</h4>
|
<h4>ETags and Resource Contention</h4>
|
||||||
|
|
Loading…
Reference in New Issue