Work on HL7org structs

This commit is contained in:
James Agnew 2015-04-20 07:31:45 -04:00
parent eddcf5f4d8
commit b42737262b
94 changed files with 25275 additions and 1237 deletions

View File

@ -3,10 +3,12 @@ package ca.uhn.fhir.android;
import static org.junit.Assert.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -56,7 +58,7 @@ public class BuiltJarIT {
* Android does not like duplicate entries in the JAR
*/
@Test
public void testJarForDuplicates() throws Exception {
public void testJarContents() throws Exception {
String wildcard = "hapi-fhir-android-*.jar";
Collection<File> files = FileUtils.listFiles(new File("target"), new WildcardFileFilter(wildcard), null);
if (files.isEmpty()) {
@ -67,6 +69,11 @@ public class BuiltJarIT {
ourLog.info("Testing file: {}", file);
ZipFile zip = new ZipFile(file);
int totalClasses = 0;
int totalMethods = 0;
TreeSet<ClassMethodCount> topMethods = new TreeSet<ClassMethodCount>();
try {
Set<String> names = new HashSet<String>();
for (Enumeration<? extends ZipEntry> iter = zip.entries(); iter.hasMoreElements();) {
@ -75,9 +82,28 @@ public class BuiltJarIT {
if (!names.add(nextName)) {
throw new Exception("File " + file + " contains duplicate contents: " + nextName);
}
if (nextName.contains("$") == false) {
if (nextName.endsWith(".class")) {
String className = nextName.replace("/", ".").replace(".class", "");
try {
Class<?> clazz = Class.forName(className);
int methodCount = clazz.getMethods().length;
topMethods.add(new ClassMethodCount(className, methodCount));
totalClasses++;
totalMethods += methodCount;
} catch (NoClassDefFoundError e) {
// ignore
} catch (ClassNotFoundException e) {
// ignore
}
}
}
}
ourLog.info("File {} contains {} entries", file, names.size());
ourLog.info("Total classes {} - Total methods {}", totalClasses, totalMethods);
ourLog.info("Top classes {}", new ArrayList<ClassMethodCount>(topMethods).subList(topMethods.size() - 10, topMethods.size()));
} finally {
zip.close();
@ -85,4 +111,42 @@ public class BuiltJarIT {
}
}
private static class ClassMethodCount implements Comparable<ClassMethodCount> {
private String myClassName;
private int myMethodCount;
public ClassMethodCount(String theClassName, int theMethodCount) {
myClassName = theClassName;
myMethodCount = theMethodCount;
}
@Override
public String toString() {
return myClassName + "[" + myMethodCount + "]";
}
@Override
public int compareTo(ClassMethodCount theO) {
return myMethodCount - theO.myMethodCount;
}
public String getClassName() {
return myClassName;
}
public void setClassName(String theClassName) {
myClassName = theClassName;
}
public int getMethodCount() {
return myMethodCount;
}
public void setMethodCount(int theMethodCount) {
myMethodCount = theMethodCount;
}
}
}

View File

@ -105,8 +105,10 @@ public abstract class BaseRuntimeElementDefinition<T extends IBase> {
return getImplementingClass().newInstance();
} else if (theArgument instanceof IValueSetEnumBinder) {
return getImplementingClass().getConstructor(IValueSetEnumBinder.class).newInstance(theArgument);
} else {
} else if (theArgument instanceof IBaseEnumFactory) {
return getImplementingClass().getConstructor(IBaseEnumFactory.class).newInstance(theArgument);
} else {
return getImplementingClass().getConstructor(theArgument.getClass()).newInstance(theArgument);
}
} catch (InstantiationException e) {
throw new ConfigurationException("Failed to instantiate type:" + getImplementingClass().getName(), e);

View File

@ -27,12 +27,14 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.text.WordUtils;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IFhirVersion;
@ -77,8 +79,9 @@ public class FhirContext {
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
private HapiLocalizer myLocalizer = new HapiLocalizer();
private volatile Map<String, RuntimeResourceDefinition> myNameToElementDefinition = Collections.emptyMap();
private Map<String, Class<? extends IBaseResource>> myNameToResourceType;
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
private volatile Map<String, RuntimeResourceDefinition> myNameToResourceDefinition = Collections.emptyMap();
private volatile Map<String, Class<? extends IBaseResource>> myNameToResourceType;
private volatile INarrativeGenerator myNarrativeGenerator;
private volatile IRestfulClientFactory myRestfulClientFactory;
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
@ -136,6 +139,14 @@ public class FhirContext {
return getLocalizer().getMessage(FhirContext.class, "unknownResourceName", theResourceName, theVersion);
}
/**
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
* for extending the core library.
*/
public BaseRuntimeElementDefinition<?> getElementDefinition(String theElementName) {
return myNameToElementDefinition.get(theElementName);
}
/**
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
* for extending the core library.
@ -241,7 +252,7 @@ public class FhirContext {
Validate.notBlank(resourceName, "Resource name must not be blank");
RuntimeResourceDefinition retVal = myNameToElementDefinition.get(resourceName);
RuntimeResourceDefinition retVal = myNameToResourceDefinition.get(resourceName);
if (retVal == null) {
Class<? extends IBaseResource> clazz = myNameToResourceType.get(resourceName.toLowerCase());
@ -401,9 +412,13 @@ public class FhirContext {
myRuntimeChildUndeclaredExtensionDefinition = scanner.getRuntimeChildUndeclaredExtensionDefinition();
}
Map<String, RuntimeResourceDefinition> nameToElementDefinition = new HashMap<String, RuntimeResourceDefinition>();
Map<String, BaseRuntimeElementDefinition<?>> nameToElementDefinition = new HashMap<String, BaseRuntimeElementDefinition<?>>();
nameToElementDefinition.putAll(myNameToElementDefinition);
nameToElementDefinition.putAll(scanner.getNameToResourceDefinitions());
nameToElementDefinition.putAll(scanner.getNameToElementDefinitions());
Map<String, RuntimeResourceDefinition> nameToResourceDefinition = new HashMap<String, RuntimeResourceDefinition>();
nameToResourceDefinition.putAll(myNameToResourceDefinition);
nameToResourceDefinition.putAll(scanner.getNameToResourceDefinition());
Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> classToElementDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
classToElementDefinition.putAll(myClassToElementDefinition);
@ -416,6 +431,7 @@ public class FhirContext {
myNameToElementDefinition = nameToElementDefinition;
myClassToElementDefinition = classToElementDefinition;
myIdToResourceDefinition = idToElementDefinition;
myNameToResourceDefinition = nameToResourceDefinition;
myNameToResourceType = scanner.getNameToResourceType();

View File

@ -40,7 +40,7 @@ public enum FhirVersionEnum {
DEV("ca.uhn.fhir.model.dev.FhirDev", null),
DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", null);
DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", DSTU2);
private final String myVersionClass;

View File

@ -101,6 +101,7 @@ class ModelScanner {
private Set<Class<? extends IBase>> myScanAlso = new HashSet<Class<? extends IBase>>();
private Set<Class<? extends ICodeEnum>> myScanAlsoCodeTable = new HashSet<Class<? extends ICodeEnum>>();
private FhirVersionEnum myVersion;
private Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinitions = new HashMap<String, BaseRuntimeElementDefinition<?>>();
ModelScanner(FhirContext theContext, FhirVersionEnum theVersion, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theExistingDefinitions, Collection<Class<? extends IElement>> theResourceTypes) throws ConfigurationException {
myContext = theContext;
@ -338,6 +339,7 @@ class ModelScanner {
resourceDef = new RuntimeCompositeDatatypeDefinition(theDatatypeDefinition, theClass);
}
myClassToElementDefinitions.put(theClass, resourceDef);
myNameToElementDefinitions.put(resourceDef.getName(), resourceDef);
scanCompositeElementForChildren(theClass, resourceDef);
}
@ -654,6 +656,7 @@ class ModelScanner {
resourceDef = new RuntimePrimitiveDatatypeDefinition(theDatatypeDefinition, theClass);
}
myClassToElementDefinitions.put(theClass, resourceDef);
myNameToElementDefinitions.put(resourceName, resourceDef);
return resourceName;
}
@ -810,4 +813,12 @@ class ModelScanner {
}
}
public Map<String, BaseRuntimeElementDefinition<?>> getNameToElementDefinitions() {
return myNameToElementDefinitions;
}
public Map<String, RuntimeResourceDefinition> getNameToResourceDefinition() {
return myNameToResourceDefinitions;
}
}

View File

@ -89,7 +89,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
BaseRuntimeElementDefinition<?> nextDef;
if (IBaseResource.class.isAssignableFrom(next)) {
elementName = getElementName() + StringUtils.capitalize(next.getSimpleName());
alternateElementName = getElementName() + "Resource";
alternateElementName = getElementName() + "Reference";
List<Class<? extends IBaseResource>> types = new ArrayList<Class<? extends IBaseResource>>();
types.add((Class<? extends IBaseResource>) next);
nextDef = new RuntimeResourceReferenceDefinition(elementName, types);
@ -107,7 +107,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
if (IBaseResource.class.isAssignableFrom(next)) {
Class<? extends IBase> refType = theContext.getVersion().getResourceReferenceType();
myDatatypeToElementDefinition.put(refType, nextDef);
alternateElementName = getElementName() + "Resource";
alternateElementName = getElementName() + "Reference";
myDatatypeToElementName.put(refType, alternateElementName);
}

View File

@ -49,13 +49,11 @@ public class RuntimeChildContainedResources extends BaseRuntimeDeclaredChildDefi
@Override
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theType) {
assert BaseContainedDt.class.isAssignableFrom(theType) || List.class.isAssignableFrom(theType);
return myElem;
}
@Override
public String getChildNameByDatatype(Class<? extends IBase> theType) {
assert BaseContainedDt.class.isAssignableFrom(theType) || List.class.isAssignableFrom(theType);
return getElementName();
}

View File

@ -141,13 +141,21 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
myDatatypeToDefinition.put(type, next.getValue());
}
// Resource Reference
myDatatypeToAttributeName.put(theContext.getVersion().getResourceReferenceType(), "valueResource");
/*
* Resource reference - The correct name is 'valueReference', but
* we allow for valueResource because some incorrect parsers may use this
*/
addReferenceBinding(theContext, theClassToElementDefinitions, "valueResource");
addReferenceBinding(theContext, theClassToElementDefinitions, "valueReference");
}
private void addReferenceBinding(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions, String value) {
myDatatypeToAttributeName.put(theContext.getVersion().getResourceReferenceType(), value);
List<Class<? extends IBaseResource>> types = new ArrayList<Class<? extends IBaseResource>>();
types.add(IBaseResource.class);
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition("valueResource", types);
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition(value, types);
def.sealAndInitialize(theContext, theClassToElementDefinitions);
myAttributeNameToDefinition.put("valueResource", def);
myAttributeNameToDefinition.put(value, def);
myDatatypeToDefinition.put(BaseResourceReferenceDt.class, def);
myDatatypeToDefinition.put(theContext.getVersion().getResourceReferenceType(), def);
}

View File

@ -20,12 +20,14 @@ package ca.uhn.fhir.model.base.resource;
* #L%
*/
import org.hl7.fhir.instance.model.api.IBaseConformance;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
//@ResourceDef(name="Conformance")
public interface BaseConformance extends IResource {
public interface BaseConformance extends IResource, IBaseConformance {
public abstract StringDt getDescriptionElement();

View File

@ -149,14 +149,14 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
* The version ID ("e.g. "456")
*/
public IdDt(String theResourceType, String theId, String theVersionId) {
this(null,theResourceType,theId,theVersionId);
this(null, theResourceType, theId, theVersionId);
}
/**
* Constructor
*
* @param theBaseUrl
* The server base URL (e.g. "http://example.com/fhir")
* The server base URL (e.g. "http://example.com/fhir")
* @param theResourceType
* The resource type (e.g. "Patient")
* @param theId
@ -201,14 +201,12 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return ObjectUtils.equals(getResourceType(), theId.getResourceType()) && ObjectUtils.equals(getIdPart(), theId.getIdPart()) && ObjectUtils.equals(getVersionIdPart(), theId.getVersionIdPart());
}
@Override
public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdDt)) {
return false;
}
IdDt id = (IdDt)theArg0;
IdDt id = (IdDt) theArg0;
return StringUtils.equals(getValueAsString(), id.getValueAsString());
}
@ -231,9 +229,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
}
/**
* Returns only the logical ID part of this ID. For example, given the ID
* "http://example,.com/fhir/Patient/123/_history/456", this method would
* return "123".
* Returns only the logical ID part of this ID. For example, given the ID "http://example,.com/fhir/Patient/123/_history/456", this method would return "123".
*/
public String getIdPart() {
return myUnqualifiedId;
@ -282,7 +278,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
StringBuilder b = new StringBuilder();
if (isNotBlank(myBaseUrl)) {
b.append(myBaseUrl);
if (myBaseUrl.charAt(myBaseUrl.length()-1)!='/') {
if (myBaseUrl.charAt(myBaseUrl.length() - 1) != '/') {
b.append('/');
}
}
@ -408,10 +404,10 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
myUnqualifiedId = null;
myUnqualifiedVersionId = null;
myResourceType = null;
} else if (theValue.charAt(0)== '#') {
} else if (theValue.charAt(0) == '#') {
myValue = theValue;
myUnqualifiedId = theValue;
myUnqualifiedVersionId=null;
myUnqualifiedVersionId = null;
myResourceType = null;
myHaveComponentParts = true;
} else {
@ -470,9 +466,8 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
}
/**
* Returns a new IdDt containing this IdDt's values but with no server base URL if one
* is present in this IdDt. For example, if this IdDt contains the ID "http://foo/Patient/1",
* this method will return a new IdDt containing ID "Patient/1".
* Returns a new IdDt containing this IdDt's values but with no server base URL if one is present in this IdDt. For example, if this IdDt contains the ID "http://foo/Patient/1", this method will
* return a new IdDt containing ID "Patient/1".
*/
public IdDt toUnqualified() {
return new IdDt(getResourceType(), getIdPart(), getVersionIdPart());
@ -552,7 +547,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
} else if (theResouce instanceof IResource) {
((IResource) theResouce).setId(new IdDt(getValue()));
} else if (theResouce instanceof IAnyResource) {
((IAnyResource) theResouce).setId(getIdPart());
((IAnyResource) theResouce).setId(getValue());
} else {
throw new IllegalArgumentException("Unknown resource class type, does not implement IResource or extend Resource");
}
@ -564,11 +559,15 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
public static IdDt of(IBaseResource theResouce) {
if (theResouce == null) {
throw new NullPointerException("theResource can not be null");
} else if (theResouce instanceof IResource) {
return ((IResource) theResouce).getId();
} else if (theResouce instanceof IAnyResource) {
// TODO: implement
throw new UnsupportedOperationException();
} else if (theResouce instanceof IBaseResource) {
IIdType retVal = ((IBaseResource) theResouce).getId();
if (retVal == null) {
return null;
} else if (retVal instanceof IdDt) {
return (IdDt) retVal;
} else {
return new IdDt(retVal.getValue());
}
} else {
throw new IllegalArgumentException("Unknown resource class type, does not implement IResource or extend Resource");
}

View File

@ -66,6 +66,7 @@ public abstract class BaseParser implements IParser {
private ContainedResources myContainedResources;
private FhirContext myContext;
private String myServerBaseUrl;
private boolean myStripVersionsFromReferences = true;
private boolean mySuppressNarratives;
public BaseParser(FhirContext theContext) {
@ -137,7 +138,6 @@ public abstract class BaseParser implements IParser {
}
protected void containResourcesForEncoding(IBaseResource theResource) {
ContainedResources contained = new ContainedResources();
containResourcesForEncoding(contained, theResource, theResource);
@ -157,17 +157,27 @@ public abstract class BaseParser implements IParser {
reference = "#" + containedId.getValue();
}
} else if (theRef.getResource().getId() != null && theRef.getResource().getId().hasIdPart()) {
reference = theRef.getResource().getId().getValue();
if (isStripVersionsFromReferences()) {
reference = theRef.getResource().getId().toVersionless().getValue();
} else {
reference = theRef.getResource().getId().getValue();
}
}
}
return reference;
} else {
if (isNotBlank(myServerBaseUrl) && StringUtils.equals(myServerBaseUrl, ref.getBaseUrl())) {
String reference = ref.toUnqualifiedVersionless().getValue();
return reference;
if (isStripVersionsFromReferences()) {
return ref.toUnqualifiedVersionless().getValue();
} else {
return ref.toUnqualified().getValue();
}
} else {
String reference = ref.toVersionless().getValue();
return reference;
if (isStripVersionsFromReferences()) {
return ref.toVersionless().getValue();
} else {
return ref.getValue();
}
}
}
}
@ -245,7 +255,13 @@ public abstract class BaseParser implements IParser {
}
protected boolean isChildContained(BaseRuntimeElementDefinition<?> childDef, boolean theIncludedResource) {
return (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES || childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCE_LIST) && getContainedResources().isEmpty() == false && theIncludedResource == false;
return (childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCES || childDef.getChildType() == ChildTypeEnum.CONTAINED_RESOURCE_LIST) && getContainedResources().isEmpty() == false
&& theIncludedResource == false;
}
@Override
public boolean isStripVersionsFromReferences() {
return myStripVersionsFromReferences;
}
@Override
@ -267,7 +283,7 @@ public abstract class BaseParser implements IParser {
List<IBase> base = def.getChildByName("base").getAccessor().getValues(retVal);
if (base != null && base.size() > 0) {
IPrimitiveType<?> baseType = (IPrimitiveType<?>) base.get(0);
IResource res = ((IResource) retVal);
IBaseResource res = ((IBaseResource) retVal);
res.setId(new IdDt(baseType.getValueAsString(), def.getName(), res.getId().getIdPart(), res.getId().getVersionIdPart()));
}
@ -287,11 +303,11 @@ public abstract class BaseParser implements IParser {
List<IBase> entryResources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry);
if (entryResources != null && entryResources.size() > 0) {
IResource res = (IResource) entryResources.get(0);
IBaseResource res = (IBaseResource) entryResources.get(0);
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(res);
String versionIdPart = res.getId().getVersionIdPart();
if (isBlank(versionIdPart)) {
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(res);
if (isBlank(versionIdPart) && res instanceof IResource) {
versionIdPart = ResourceMetadataKeyEnum.VERSION.get((IResource) res);
}
res.setId(new IdDt(baseType.getValueAsString(), resDef.getName(), res.getId().getIdPart(), versionIdPart));
@ -335,6 +351,12 @@ public abstract class BaseParser implements IParser {
return this;
}
@Override
public IParser setStripVersionsFromReferences(boolean theStripVersionsFromReferences) {
myStripVersionsFromReferences = theStripVersionsFromReferences;
return this;
}
@Override
public IParser setSuppressNarratives(boolean theSuppressNarratives) {
mySuppressNarratives = theSuppressNarratives;

View File

@ -28,7 +28,6 @@ import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
/**
@ -178,4 +177,28 @@ public interface IParser {
*/
IParser setServerBaseUrl(String theUrl);
/**
* If set to <code>true<code> (which is the default), resource references containing a version
* will have the version removed when the resource is encoded. This is generally good behaviour because
* in most situations, references from one resource to another should be to the resource by ID, not
* by ID and version. In some cases though, it may be desirable to preserve the version in resource
* links. In that case, this value should be set to <code>false</code>.
*
* @param theStripVersionsFromReferences Set this to <code>false<code> to prevent the parser from removing
* resource versions from references.
* @return Returns an instance of <code>this</code> parser so that method calls can be chained together
*/
IParser setStripVersionsFromReferences(boolean theStripVersionsFromReferences);
/**
* If set to <code>true<code> (which is the default), resource references containing a version
* will have the version removed when the resource is encoded. This is generally good behaviour because
* in most situations, references from one resource to another should be to the resource by ID, not
* by ID and version. In some cases though, it may be desirable to preserve the version in resource
* links. In that case, this value should be set to <code>false</code>.
*
* @return Returns the parser instance's configuration setting for stripping versions from resource references when encoding. Default is <code>true</code>.
*/
boolean isStripVersionsFromReferences();
}

View File

@ -358,13 +358,14 @@ public class JsonParser extends BaseParser implements IParser {
switch (theChildDef.getChildType()) {
case ID_DATATYPE: {
IIdType value = (IIdType) theNextValue;
if (isBlank(value.getIdPart())) {
String encodedValue = "id".equals(theChildName) ? value.getIdPart() : value.getValue();
if (isBlank(encodedValue)) {
break;
}
if (theChildName != null) {
theWriter.write(theChildName, value.getIdPart());
theWriter.write(theChildName, encodedValue);
} else {
theWriter.write(value.getIdPart());
theWriter.write(encodedValue);
}
break;
}
@ -410,8 +411,8 @@ public class JsonParser extends BaseParser implements IParser {
} else {
theWriter.writeStartObject();
}
if (theNextValue instanceof ExtensionDt) {
theWriter.write("url", ((ExtensionDt) theNextValue).getUrlAsString());
if (theNextValue instanceof IBaseExtension) {
theWriter.write("url", ((IBaseExtension<?>) theNextValue).getUrl());
}
encodeCompositeElementToStreamWriter(theResDef, theResource, theNextValue, theWriter, childCompositeDef, theIsSubElementWithinResource);
theWriter.writeEnd();
@ -871,7 +872,7 @@ public class JsonParser extends BaseParser implements IParser {
IBaseHasExtensions element = (IBaseHasExtensions) theElement;
List<? extends IBaseExtension<?>> ext = element.getExtension();
for (IBaseExtension<?> next : ext) {
if (next == null || next.isEmpty()) {
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
continue;
}
extensions.add(new HeldExtension(next, false));
@ -1050,11 +1051,17 @@ public class JsonParser extends BaseParser implements IParser {
if ("resourceType".equals(nextName)) {
continue;
} else if ("id".equals(nextName)) {
if (theObject.isNull(nextName)) {
continue;
}
elementId = theObject.getString(nextName);
if (myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
continue;
}
} else if ("_id".equals(nextName)) {
if (theObject.isNull(nextName)) {
continue;
}
// _id is incorrect, but some early examples in the FHIR spec used it
elementId = theObject.getString(nextName);
continue;
@ -1082,8 +1089,8 @@ public class JsonParser extends BaseParser implements IParser {
IBase object = (IBase) theState.getObject();
if (object instanceof IIdentifiableElement) {
((IIdentifiableElement) object).setElementSpecificId(elementId);
} else if (object instanceof IResource) {
((IResource) object).setId(new IdDt(elementId));
} else if (object instanceof IBaseResource) {
((IBaseResource) object).getId().setValue(elementId);
}
}
}
@ -1196,31 +1203,35 @@ public class JsonParser extends BaseParser implements IParser {
@Override
public <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) {
JsonReader reader = Json.createReader(theReader);
JsonObject object = reader.readObject();
try {
JsonReader reader = Json.createReader(theReader);
JsonObject object = reader.readObject();
JsonValue resourceTypeObj = object.get("resourceType");
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
String resourceType = ((JsonString) resourceTypeObj).getString();
JsonValue resourceTypeObj = object.get("resourceType");
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
String resourceType = ((JsonString) resourceTypeObj).getString();
RuntimeResourceDefinition def;
if (theResourceType != null) {
def = myContext.getResourceDefinition(theResourceType);
} else {
def = myContext.getResourceDefinition(resourceType);
RuntimeResourceDefinition def;
if (theResourceType != null) {
def = myContext.getResourceDefinition(theResourceType);
} else {
def = myContext.getResourceDefinition(resourceType);
}
ParserState<? extends IBaseResource> state = ParserState.getPreResourceInstance(def.getImplementingClass(), myContext, true);
state.enteringNewElement(null, def.getName());
parseChildren(object, state);
state.endingElement();
@SuppressWarnings("unchecked")
T retVal = (T) state.getObject();
return retVal;
} catch (JsonParsingException e) {
throw new DataFormatException("Failed to parse JSON: " + e.getMessage(), e);
}
ParserState<? extends IBaseResource> state = ParserState.getPreResourceInstance(def.getImplementingClass(), myContext, true);
state.enteringNewElement(null, def.getName());
parseChildren(object, state);
state.endingElement();
@SuppressWarnings("unchecked")
T retVal = (T) state.getObject();
return retVal;
}
@Override

View File

@ -42,6 +42,7 @@ import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
@ -1682,7 +1683,7 @@ class ParserState<T> {
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance();
ICompositeType newChildInstance = (ICompositeType) compositeTarget.newInstance();
myExtension.setValue(newChildInstance);
ElementCompositeState newState = new ElementCompositeState(getPreResourceState(), compositeTarget, newChildInstance);
push(newState);
@ -1714,6 +1715,9 @@ class ParserState<T> {
case UNDECL_EXT:
case EXTENSION_DECLARED:
case CONTAINED_RESOURCES:
case CONTAINED_RESOURCE_LIST:
case ID_DATATYPE:
case PRIMITIVE_XHTML_HL7ORG:
break;
}
}
@ -1952,6 +1956,17 @@ class ParserState<T> {
if (myTarget == null) {
myObject = (T) getCurrentElement();
}
if (getCurrentElement() instanceof IDomainResource) {
IDomainResource elem = (IDomainResource) getCurrentElement();
String resourceName = myContext.getResourceDefinition(elem).getName();
String versionId = elem.getMeta().getVersionId();
if (StringUtils.isNotBlank(versionId)) {
elem.getIdElement().setValue(resourceName + "/" + elem.getId().getIdPart() + "/_history/" + versionId);
} else {
elem.getIdElement().setValue(resourceName + "/" + elem.getId().getIdPart());
}
}
}
@Override

View File

@ -458,11 +458,11 @@ public class XmlParser extends BaseParser implements IParser {
switch (childDef.getChildType()) {
case ID_DATATYPE: {
IIdType pd = (IIdType) nextValue;
String value = pd.getIdPart();
IIdType value = (IIdType) nextValue;
String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue();
if (value != null) {
theEventWriter.writeStartElement(childName);
theEventWriter.writeAttribute("value", value);
theEventWriter.writeAttribute("value", encodedValue);
encodeExtensionsIfPresent(theResource, theEventWriter, nextValue, theIncludedResource);
theEventWriter.writeEndElement();
}
@ -494,7 +494,7 @@ public class XmlParser extends BaseParser implements IParser {
IReference ref = (IReference) nextValue;
if (!ref.isEmpty()) {
theEventWriter.writeStartElement(childName);
encodeResourceReferenceToStreamWriter(theEventWriter, ref);
encodeResourceReferenceToStreamWriter(theEventWriter, ref, theResource, theIncludedResource);
theEventWriter.writeEndElement();
}
break;
@ -674,9 +674,11 @@ public class XmlParser extends BaseParser implements IParser {
return retVal;
}
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, IReference theRef) throws XMLStreamException {
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, IReference theRef, IBaseResource theResource, boolean theIncludedResource) throws XMLStreamException {
String reference = determineReferenceText(theRef);
encodeExtensionsIfPresent(theResource, theEventWriter, theRef, theIncludedResource);
if (StringUtils.isNotBlank(reference)) {
theEventWriter.writeStartElement(RESREF_REFERENCE);
theEventWriter.writeAttribute("value", reference);
@ -890,7 +892,7 @@ public class XmlParser extends BaseParser implements IParser {
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
for (IBaseExtension<?> next : theExtensions) {
if (next == null) {
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
continue;
}

View File

@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.client;
* #L%
*/
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.Reader;
@ -39,6 +40,7 @@ import org.apache.http.client.methods.HttpRequestBase;
import org.hl7.fhir.instance.model.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IIdType;
@ -73,6 +75,8 @@ import ca.uhn.fhir.rest.gclient.IDelete;
import ca.uhn.fhir.rest.gclient.IDeleteTyped;
import ca.uhn.fhir.rest.gclient.IDeleteWithQuery;
import ca.uhn.fhir.rest.gclient.IDeleteWithQueryTyped;
import ca.uhn.fhir.rest.gclient.IFetchConformanceTyped;
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
import ca.uhn.fhir.rest.gclient.IGetPage;
import ca.uhn.fhir.rest.gclient.IGetPageTyped;
import ca.uhn.fhir.rest.gclient.IGetTags;
@ -141,8 +145,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
myContext = theContext;
}
@Override
public BaseConformance conformance() {
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
throw new IllegalArgumentException("Must call conformance(" + IBaseConformance.class.getSimpleName() + ") for HL7.org structures");
}
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation();
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
@ -166,7 +175,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return myContext;
}
@Override
public MethodOutcome create(IResource theResource) {
BaseHttpClientInvocation invocation = MethodUtil.createCreateInvocation(theResource, myContext);
@ -352,7 +360,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override
public IOperation operation() {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) == false) {
throw new IllegalStateException("Operations are only supported in FHIR DSTU2 and later. This client was created using a context configured for " + myContext.getVersion().getVersion().name());
throw new IllegalStateException("Operations are only supported in FHIR DSTU2 and later. This client was created using a context configured for "
+ myContext.getVersion().getVersion().name());
}
return new OperationInternal();
}
@ -362,6 +371,11 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new ReadInternal();
}
@Override
public IFetchConformanceUntyped fetchConformance() {
return new FetchConformanceInternal();
}
@Override
public <T extends IBaseResource> T read(Class<T> theType, String theId) {
return read(theType, new IdDt(theId));
@ -374,7 +388,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IResource read(UriDt theUrl) {
public IBaseResource read(UriDt theUrl) {
IdDt id = new IdDt(theUrl);
String resourceType = id.getResourceType();
if (isBlank(resourceType)) {
@ -384,7 +398,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
if (def == null) {
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
}
return (IResource) read(def.getImplementingClass(), id);
return (IBaseResource) read(def.getImplementingClass(), id);
}
@Override
@ -449,7 +463,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public List<IResource> transaction(List<IResource> theResources) {
public List<IBaseResource> transaction(List<IBaseResource> theResources) {
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(theResources, myContext);
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
@ -457,7 +471,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
Bundle resp = invokeClient(myContext, new BundleResponseHandler(null), invocation, myLogRequestAndResponse);
return resp.toListOfResources();
return new ArrayList<IBaseResource>(resp.toListOfResources());
}
@Override
@ -680,7 +694,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public ICreateTyped resource(IResource theResource) {
public ICreateTyped resource(IBaseResource theResource) {
Validate.notNull(theResource, "Resource can not be null");
myResource = theResource;
return this;
@ -736,7 +750,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> implements IDelete, IDeleteTyped, IDeleteWithQuery, IDeleteWithQueryTyped {
private CriterionList myCriterionList;
private IdDt myId;
private IIdType myId;
private String myResourceType;
private String mySearchUrl;
@ -775,7 +789,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IDeleteTyped resourceById(IdDt theId) {
public IDeleteTyped resourceById(IIdType theId) {
Validate.notNull(theId, "theId can not be null");
if (theId.hasResourceType() == false || theId.hasIdPart() == false) {
throw new IllegalArgumentException("theId must contain a resource type and logical ID at a minimum (e.g. Patient/1234)found: " + theId.getValue());
@ -914,7 +928,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped {
private Integer myCount;
private IdDt myId;
private IIdType myId;
private Class<? extends IBaseBundle> myReturnType;
private InstantDt mySince;
private Class<? extends IBaseResource> myType;
@ -967,7 +981,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IHistoryUntyped onInstance(IdDt theId) {
public IHistoryUntyped onInstance(IIdType theId) {
if (theId.hasResourceType() == false) {
throw new IllegalArgumentException("Resource ID does not have a resource type: " + theId.getValue());
}
@ -1026,7 +1040,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("rawtypes")
private class OperationInternal extends BaseClientExecutable implements IOperation, IOperationUnnamed, IOperationUntyped, IOperationUntypedWithInput {
private IdDt myId;
private IIdType myId;
private String myOperationName;
private IBaseParameters myParameters;
private Class<? extends IBaseResource> myType;
@ -1054,7 +1068,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
handler = new ResourceResponseHandler(myParameters.getClass(), null);
Object retVal = invoke(null, handler, invocation);
if (myContext.getResourceDefinition((IBaseResource)retVal).getName().equals("Parameters")) {
if (myContext.getResourceDefinition((IBaseResource) retVal).getName().equals("Parameters")) {
return retVal;
} else {
RuntimeResourceDefinition def = myContext.getResourceDefinition("Parameters");
@ -1075,12 +1089,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override
public IOperationUntyped named(String theName) {
Validate.notBlank(theName, "theName can not be null");
myOperationName =theName;
myOperationName = theName;
return this;
}
@Override
public IOperationUnnamed onInstance(IdDt theId) {
public IOperationUnnamed onInstance(IIdType theId) {
myId = theId;
return this;
}
@ -1113,7 +1127,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type: " + theOutputParameterType.getName());
}
if (!"Parameters".equals(def.getName())) {
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type for a resource named " + "Parameters" + " - " + theOutputParameterType.getName() + " is a resource named: " + def.getName());
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type for a resource named " + "Parameters" + " - " + theOutputParameterType.getName()
+ " is a resource named: " + def.getName());
}
myParameters = (IBaseParameters) def.newInstance();
return this;
@ -1290,7 +1305,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
private final class ResourceListResponseHandler implements IClientResponseHandler<List<IResource>> {
private final class ResourceListResponseHandler implements IClientResponseHandler<List<IBaseResource>> {
private Class<? extends IResource> myType;
@ -1300,17 +1315,17 @@ public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("unchecked")
@Override
public List<IResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
public List<IBaseResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
BaseServerResponseException {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
Class<? extends IBaseResource> bundleType = myContext.getResourceDefinition("Bundle").getImplementingClass();
ResourceResponseHandler<IBaseResource> handler = new ResourceResponseHandler<IBaseResource>((Class<IBaseResource>) bundleType, null);
IBaseResource response = handler.invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders);
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
bundleFactory.initializeWithBundleResource((IResource) response);
bundleFactory.initializeWithBundleResource((IBaseResource) response);
return bundleFactory.toListOfResources();
} else {
return new BundleResponseHandler(myType).invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders).toListOfResources();
return new ArrayList<IBaseResource>(new BundleResponseHandler(myType).invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders).toListOfResources());
}
}
}
@ -1340,7 +1355,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
}
private class SearchInternal extends BaseClientExecutable<IQuery, Bundle> implements IQuery, IUntypedQuery {
@SuppressWarnings({ "rawtypes", "unchecked" })
private class SearchInternal extends BaseClientExecutable<IQuery<Object>, Object> implements IQuery<Object>, IUntypedQuery {
private String myCompartmentName;
private CriterionList myCriterion = new CriterionList();
@ -1352,6 +1368,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private Class<? extends IBaseResource> myResourceType;
private SearchStyleEnum mySearchStyle;
private List<SortInternal> mySort = new ArrayList<SortInternal>();
private Class<? extends IBaseBundle> myReturnBundleType;
public SearchInternal() {
myResourceType = null;
@ -1365,7 +1382,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public Bundle execute() {
public IBase execute() {
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
// Map<String, List<String>> initial = createExtraParams();
@ -1391,7 +1408,17 @@ public class GenericClient extends BaseClient implements IGenericClient {
addParam(params, Constants.PARAM_COUNT, Integer.toString(myParamLimit));
}
BundleResponseHandler binding = new BundleResponseHandler(myResourceType);
if (myReturnBundleType == null && myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
throw new IllegalArgumentException("When using the client with HL7.org structures, you must specify "
+ "the bundle return type for the client by adding \".returnBundle(org.hl7.fhir.instance.model.Bundle.class)\" to your search method call before the \".execute()\" method");
}
IClientResponseHandler binding;
if (myReturnBundleType != null) {
binding = new ResourceResponseHandler(myReturnBundleType, null);
} else {
binding = new BundleResponseHandler(myResourceType);
}
IdDt resourceId = myResourceId != null ? new IdDt(myResourceId) : null;
@ -1407,7 +1434,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IQuery forResource(Class<? extends IResource> theResourceType) {
public IQuery forResource(Class<? extends IBaseResource> theResourceType) {
setType(theResourceType);
return this;
}
@ -1434,7 +1461,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
private void setType(Class<? extends IResource> theResourceType) {
private void setType(Class<? extends IBaseResource> theResourceType) {
myResourceType = theResourceType;
RuntimeResourceDefinition definition = myContext.getResourceDefinition(theResourceType);
myResourceName = definition.getName();
@ -1472,13 +1499,23 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IQuery revinclude(Include theInclude) {
public IQuery revInclude(Include theInclude) {
myRevInclude.add(theInclude);
return this;
}
@Override
public IClientExecutable returnBundle(Class theClass) {
if (theClass == null) {
throw new NullPointerException("theClass must not be null");
}
myReturnBundleType = theClass;
return this;
}
}
@SuppressWarnings("rawtypes")
private static class SortInternal implements ISort {
private SearchInternal myFor;
@ -1537,14 +1574,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
private final class TransactionExecutable<T> extends BaseClientExecutable<ITransactionTyped<T>, T> implements ITransactionTyped<T> {
private Bundle myBundle;
private List<IResource> myResources;
private List<IBaseResource> myResources;
private IBaseBundle myBaseBundle;
public TransactionExecutable(Bundle theResources) {
myBundle = theResources;
}
public TransactionExecutable(List<IResource> theResources) {
public TransactionExecutable(List<IBaseResource> theResources) {
myResources = theResources;
}
@ -1561,7 +1598,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myResources, myContext);
return (T) invoke(params, binding, invocation);
} else if (myBaseBundle != null) {
ResourceResponseHandler binding = new ResourceResponseHandler(myBaseBundle.getClass(),null);
ResourceResponseHandler binding = new ResourceResponseHandler(myBaseBundle.getClass(), null);
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBaseBundle, myContext);
return (T) invoke(params, binding, invocation);
} else {
@ -1582,9 +1619,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public ITransactionTyped<List<IResource>> withResources(List<IResource> theResources) {
public ITransactionTyped<List<IBaseResource>> withResources(List<IBaseResource> theResources) {
Validate.notNull(theResources, "theResources must not be null");
return new TransactionExecutable<List<IResource>>(theResources);
return new TransactionExecutable<List<IBaseResource>>(theResources);
}
@Override
@ -1658,7 +1695,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IUpdateTyped resource(IResource theResource) {
public IUpdateTyped resource(IBaseResource theResource) {
Validate.notNull(theResource, "Resource can not be null");
myResource = theResource;
return this;
@ -1703,4 +1740,36 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private class FetchConformanceInternal extends BaseClientExecutable implements IFetchConformanceUntyped, IFetchConformanceTyped {
private RuntimeResourceDefinition myType;
@Override
public Object execute() {
ResourceResponseHandler binding = new ResourceResponseHandler(myType.getImplementingClass(), null);
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation();
return invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
}
@Override
public <T extends IBaseConformance> IFetchConformanceTyped<T> ofType(Class<T> theResourceType) {
Validate.notNull(theResourceType, "theResourceType must not be null");
myType = myContext.getResourceDefinition(theResourceType);
if (myType == null) {
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theResourceType));
}
return this;
}
}
}

View File

@ -36,6 +36,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.gclient.ICreate;
import ca.uhn.fhir.rest.gclient.IDelete;
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
import ca.uhn.fhir.rest.gclient.IGetPage;
import ca.uhn.fhir.rest.gclient.IGetTags;
import ca.uhn.fhir.rest.gclient.IHistory;
@ -49,9 +50,17 @@ public interface IGenericClient extends IRestfulClient {
/**
* Retrieves and returns the server conformance statement
*
* @deprecated Use {@link #fetchConformance()} instead
*/
@Deprecated
BaseConformance conformance();
/**
* Retrieves the server's conformance statement
*/
IFetchConformanceUntyped fetchConformance();
/**
* Fluent method for the "create" operation, which creates a new resource instance on the server
*/
@ -217,7 +226,7 @@ public interface IGenericClient extends IRestfulClient {
* The absolute URL, e.g. "http://example.com/fhir/Patient/123"
* @return The returned resource from the server
*/
IResource read(UriDt theUrl);
IBaseResource read(UriDt theUrl);
/**
* Register a new interceptor for this client. An interceptor can be used to add additional logging, or add security
@ -274,7 +283,7 @@ public interface IGenericClient extends IRestfulClient {
*
*/
@Deprecated
List<IResource> transaction(List<IResource> theResources);
List<IBaseResource> transaction(List<IBaseResource> theResources);
/**
* Remove an intercaptor that was previously registered using
@ -363,4 +372,5 @@ public interface IGenericClient extends IRestfulClient {
*/
<T extends IBaseResource> T vread(Class<T> theType, String theId, String theVersionId);
}

View File

@ -43,15 +43,17 @@ import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.base.resource.BaseConformance;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.FhirTerser;
public class RestfulClientFactory implements IRestfulClientFactory {
@ -267,26 +269,34 @@ public class RestfulClientFactory implements IRestfulClientFactory {
myHttpClient = null;
}
@SuppressWarnings("unchecked")
private void validateServerBase(String theServerBase, HttpClient theHttpClient) {
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
client.setDontValidateConformance(true);
BaseConformance conformance;
IBaseResource conformance;
try {
conformance = client.conformance();
@SuppressWarnings("rawtypes")
Class implementingClass = myContext.getResourceDefinition("Conformance").getImplementingClass();
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
} catch (FhirClientConnectionException e) {
throw new FhirClientConnectionException(myContext.getLocalizer().getMessage(RestfulClientFactory.class, "failedToRetrieveConformance", theServerBase + Constants.URL_TOKEN_METADATA), e);
}
String serverFhirVersionString = conformance.getFhirVersionElement().getValueAsString();
FhirTerser t = myContext.newTerser();
String serverFhirVersionString = null;
Object value = t.getSingleValueOrNull(conformance, "fhirVersion");
if (value instanceof IPrimitiveType) {
serverFhirVersionString = ((IPrimitiveType<?>) value).getValueAsString();
}
FhirVersionEnum serverFhirVersionEnum = null;
if (StringUtils.isBlank(serverFhirVersionString)) {
// we'll be lenient and accept this
} else {
if (serverFhirVersionString.startsWith("0.80") || serverFhirVersionString.startsWith("0.0.8")) {
serverFhirVersionEnum = FhirVersionEnum.DSTU1;
} else if (serverFhirVersionString.startsWith("0.4")) {
} else if (serverFhirVersionString.startsWith("0.4") || serverFhirVersionString.startsWith("0.5")) {
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
} else {
// we'll be lenient and accept this

View File

@ -21,8 +21,7 @@ package ca.uhn.fhir.rest.gclient;
*/
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.primitive.IdDt;
import org.hl7.fhir.instance.model.api.IIdType;
public interface IBaseOn<T> {
@ -43,6 +42,6 @@ public interface IBaseOn<T> {
*
* @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
*/
T onInstance(IdDt theId);
T onInstance(IIdType theId);
}

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.gclient;
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.IBaseResource;
/*
* #%L
@ -23,7 +23,7 @@ import ca.uhn.fhir.model.api.IResource;
*/
public interface ICreate {
ICreateTyped resource(IResource theResource);
ICreateTyped resource(IBaseResource theResource);
ICreateTyped resource(String theResourceAsText);
}

View File

@ -1,7 +1,8 @@
package ca.uhn.fhir.rest.gclient;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
/*
* #%L
@ -27,7 +28,7 @@ public interface IDelete {
IDeleteTyped resource(IResource theResource);
IDeleteTyped resourceById(IdDt theId);
IDeleteTyped resourceById(IIdType theId);
IDeleteTyped resourceById(String theResourceType, String theLogicalId);

View File

@ -0,0 +1,7 @@
package ca.uhn.fhir.rest.gclient;
import org.hl7.fhir.instance.model.api.IBaseConformance;
public interface IFetchConformanceTyped<T extends IBaseConformance> extends IClientExecutable<IFetchConformanceTyped<T>, T> {
}

View File

@ -0,0 +1,12 @@
package ca.uhn.fhir.rest.gclient;
import org.hl7.fhir.instance.model.api.IBaseConformance;
public interface IFetchConformanceUntyped {
/**
* Retrieve the conformance statement using the given model type
*/
<T extends IBaseConformance> IFetchConformanceTyped<T> ofType(Class<T> theType);
}

View File

@ -20,20 +20,21 @@ package ca.uhn.fhir.rest.gclient;
* #L%
*/
import ca.uhn.fhir.model.api.Bundle;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.method.SearchStyleEnum;
public interface IQuery extends IClientExecutable<IQuery, Bundle>, IBaseQuery<IQuery> {
public interface IQuery<T> extends IClientExecutable<IQuery<T>, T>, IBaseQuery<IQuery<T>> {
/**
* Add an "_include" specification
*/
IQuery include(Include theInclude);
IQuery<T> include(Include theInclude);
ISort sort();
ISort<T> sort();
IQuery limitTo(int theLimitTo);
IQuery<T> limitTo(int theLimitTo);
/**
* Forces the query to perform the search using the given method (allowable methods are described in the
@ -42,15 +43,21 @@ public interface IQuery extends IClientExecutable<IQuery, Bundle>, IBaseQuery<IQ
* @see SearchStyleEnum
* @since 0.6
*/
IQuery usingStyle(SearchStyleEnum theStyle);
IQuery<T> usingStyle(SearchStyleEnum theStyle);
IQuery withIdAndCompartment(String theResourceId, String theCompartmentName);
IQuery<T> withIdAndCompartment(String theResourceId, String theCompartmentName);
/**
* Add a "_revinclude" specification
*
* @since 1.0
*/
IQuery revinclude(Include theIncludeTarget);
IQuery<T> revInclude(Include theIncludeTarget);
/**
* Request that the client return the specified bundle type, e.g. <code>org.hl7.fhir.instance.model.Bundle.class</code>
* or <code>ca.uhn.fhir.model.dstu2.resource.Bundle.class</code>
*/
<B extends IBaseBundle> IClientExecutable<IQuery<B>, B> returnBundle(Class<B> theClass);
}

View File

@ -20,12 +20,12 @@ package ca.uhn.fhir.rest.gclient;
* #L%
*/
public interface ISort {
public interface ISort<T> {
IQuery ascending(IParam theParam);
IQuery<T> ascending(IParam theParam);
IQuery defaultOrder(IParam theParam);
IQuery<T> defaultOrder(IParam theParam);
IQuery descending(IParam theParam);
IQuery<T> descending(IParam theParam);
}

View File

@ -22,17 +22,17 @@ package ca.uhn.fhir.rest.gclient;
import java.util.List;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
public interface ITransaction {
/**
* Use a list of resources as the transaction input
*/
ITransactionTyped<List<IResource>> withResources(List<IResource> theResources);
ITransactionTyped<List<IBaseResource>> withResources(List<IBaseResource> theResources);
/**
* Use a DSTU1 Bundle (Atom) as the transaction input

View File

@ -20,15 +20,17 @@ package ca.uhn.fhir.rest.gclient;
* #L%
*/
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.api.Bundle;
public interface IUntypedQuery {
IQuery forAllResources();
IQuery<Bundle> forAllResources();
IQuery forResource(String theResourceName);
IQuery<Bundle> forResource(String theResourceName);
IQuery forResource(Class<? extends IResource> theClass);
IQuery<Bundle> forResource(Class<? extends IBaseResource> theClass);
}

View File

@ -20,11 +20,11 @@ package ca.uhn.fhir.rest.gclient;
* #L%
*/
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.IBaseResource;
public interface IUpdate {
IUpdateTyped resource(IResource theResource);
IUpdateTyped resource(IBaseResource theResource);
IUpdateTyped resource(String theResourceBody);

View File

@ -38,7 +38,6 @@ import org.hl7.fhir.instance.model.api.IBaseBinary;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.DataFormatException;
@ -64,7 +63,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
private String myIfNoneExistString;
private Map<String, List<String>> myParams;
private final IBaseResource myResource;
private final List<IResource> myResources;
private final List<IBaseResource> myResources;
private final TagList myTagList;
private final String myUrlPath;
@ -104,7 +103,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
myBundleType = null;
}
public BaseHttpClientInvocationWithContents(FhirContext theContext, List<IResource> theResources, BundleTypeEnum theBundleType) {
public BaseHttpClientInvocationWithContents(FhirContext theContext, List<IBaseResource> theResources, BundleTypeEnum theBundleType) {
myContext = theContext;
myResource = null;
myTagList = null;

View File

@ -510,9 +510,9 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
} else if (response instanceof IResource) {
return BundleProviders.newList((IResource) response);
} else if (response instanceof Collection) {
List<IResource> retVal = new ArrayList<IResource>();
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (Object next : ((Collection<?>) response)) {
retVal.add((IResource) next);
retVal.add((IBaseResource) next);
}
return BundleProviders.newList(retVal);
} else {

View File

@ -255,7 +255,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
case BUNDLE: {
if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) {
IResource resource;
IBaseResource resource;
if (resultObj instanceof IBundleProvider) {
IBundleProvider result = (IBundleProvider) resultObj;
resource = result.getResources(0, 1).get(0);
@ -326,7 +326,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
throw new InternalErrorException("Method returned multiple resources");
}
IResource resource = result.getResources(0, 1).get(0);
IBaseResource resource = result.getResources(0, 1).get(0);
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
IServerInterceptor next = theServer.getInterceptors().get(i);

View File

@ -26,6 +26,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -140,7 +142,7 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
return retVal;
}
public static HttpDeleteClientInvocation createDeleteInvocation(IdDt theId) {
public static HttpDeleteClientInvocation createDeleteInvocation(IIdType theId) {
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theId);
return retVal;
}

View File

@ -186,15 +186,15 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
}
@Override
public List<IResource> getResources(int theFromIndex, int theToIndex) {
List<IResource> retVal = resources.getResources(theFromIndex, theToIndex);
public List<IBaseResource> getResources(int theFromIndex, int theToIndex) {
List<IBaseResource> retVal = resources.getResources(theFromIndex, theToIndex);
int index = theFromIndex;
for (IResource nextResource : retVal) {
for (IBaseResource nextResource : retVal) {
if (nextResource.getId() == null || isBlank(nextResource.getId().getIdPart())) {
throw new InternalErrorException("Server provided resource at index " + index + " with no ID set (using IResource#setId(IdDt))");
}
if (isBlank(nextResource.getId().getVersionIdPart())) {
IdDt versionId = (IdDt) ResourceMetadataKeyEnum.VERSION_ID.get(nextResource);
if (isBlank(nextResource.getId().getVersionIdPart()) && nextResource instanceof IResource) {
IdDt versionId = (IdDt) ResourceMetadataKeyEnum.VERSION_ID.get((IResource) nextResource);
if (versionId == null || versionId.isEmpty()) {
throw new InternalErrorException("Server provided resource at index " + index + " with no Version ID set (using IResource#setId(IdDt))");
}

View File

@ -25,8 +25,8 @@ import java.util.Map;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpRequestBase;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.server.EncodingEnum;
@ -35,7 +35,7 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
private String myUrlPath;
private Map<String, List<String>> myParams;
public HttpDeleteClientInvocation(IdDt theId) {
public HttpDeleteClientInvocation(IIdType theId) {
super();
myUrlPath = theId.toUnqualifiedVersionless().getValue();
}

View File

@ -29,7 +29,6 @@ import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
@ -48,7 +47,7 @@ public class HttpPostClientInvocation extends BaseHttpClientInvocationWithConten
super(theContext, theTagList, theUrlExtension);
}
public HttpPostClientInvocation(FhirContext theContext, List<IResource> theResources, BundleTypeEnum theBundleType) {
public HttpPostClientInvocation(FhirContext theContext, List<IBaseResource> theResources, BundleTypeEnum theBundleType) {
super(theContext, theResources, theBundleType);
}

View File

@ -45,7 +45,6 @@ import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.Operation;
@ -237,12 +236,12 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
Map<String, List<String>> params = new HashMap<String, List<String>>();
for (Object nextParameter : parameters) {
StringDt nextNameDt = (StringDt) t.getSingleValueOrNull((IBase) nextParameter, "name");
IPrimitiveType<?> nextNameDt = (IPrimitiveType<?>) t.getSingleValueOrNull((IBase) nextParameter, "name");
if (nextNameDt == null || nextNameDt.isEmpty()) {
ourLog.warn("Ignoring input parameter with no value in Parameters.parameter.name in operation client invocation");
continue;
}
String nextName = nextNameDt.getValue();
String nextName = nextNameDt.getValueAsString();
if (!params.containsKey(nextName)) {
params.put(nextName, new ArrayList<String>());
}

View File

@ -35,6 +35,7 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildPrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -51,6 +52,7 @@ class OperationParamBinder implements IParameter {
private final String myName;
private Class<?> myParameterType;
@SuppressWarnings("rawtypes")
private Class<? extends Collection> myInnerCollectionType;
private final String myOperationName;
@ -72,30 +74,36 @@ class OperationParamBinder implements IParameter {
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
addClientParameter(theSourceClientArgument, theTargetResource, paramChild, paramChildElem);
addClientParameter(theContext, theSourceClientArgument, theTargetResource, paramChild, paramChildElem);
}
private void addClientParameter(Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
private void addClientParameter(FhirContext theContext, Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
if (theSourceClientArgument instanceof IBaseResource) {
IBase parameter = createParameterRepetition(theTargetResource, paramChild, paramChildElem);
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem);
paramChildElem.getChildByName("resource").getMutator().addValue(parameter, (IBaseResource) theSourceClientArgument);
} else if (theSourceClientArgument instanceof IBaseDatatype) {
IBase parameter = createParameterRepetition(theTargetResource, paramChild, paramChildElem);
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem);
paramChildElem.getChildByName("value[x]").getMutator().addValue(parameter, (IBaseDatatype) theSourceClientArgument);
} else if (theSourceClientArgument instanceof Collection) {
Collection<?> collection = (Collection<?>) theSourceClientArgument;
for (Object next : collection) {
addClientParameter(next, theTargetResource, paramChild, paramChildElem);
addClientParameter(theContext, next, theTargetResource, paramChild, paramChildElem);
}
} else {
throw new IllegalArgumentException("Don't know how to handle value of type " + theSourceClientArgument.getClass() + " for paramater " + myName);
}
}
private IBase createParameterRepetition(IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
private IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
IBase parameter = paramChildElem.newInstance();
paramChild.getMutator().addValue(theTargetResource, parameter);
paramChildElem.getChildByName("name").getMutator().addValue(parameter, new StringDt(myName));
IPrimitiveType<?> value;
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
value = (IPrimitiveType<?>) theContext.getElementDefinition("string").newInstance(myName);
} else {
value = new StringDt(myName);
}
paramChildElem.getChildByName("name").getMutator().addValue(parameter, value);
return parameter;
}

View File

@ -205,8 +205,8 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
if (theRequest.getServer().getETagSupport() == ETagSupportEnum.ENABLED) {
String ifNoneMatch = ((Request)theRequest).getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
if (retVal.size() == 1 && StringUtils.isNotBlank(ifNoneMatch)) {
List<IResource> responseResources = retVal.getResources(0, 1);
IResource responseResource = responseResources.get(0);
List<IBaseResource> responseResources = retVal.getResources(0, 1);
IBaseResource responseResource = responseResources.get(0);
ifNoneMatch = MethodUtil.parseETagValue(ifNoneMatch);
if (responseResource.getId() != null && responseResource.getId().hasVersionIdPart()) {

View File

@ -20,13 +20,14 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.IdentityHashMap;
import java.util.List;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import ca.uhn.fhir.context.ConfigurationException;
@ -117,7 +118,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
return createTransactionInvocation(bundle, context);
} else {
@SuppressWarnings("unchecked")
List<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex];
List<IBaseResource> resources = (List<IBaseResource>) theArgs[myTransactionParamIndex];
return createTransactionInvocation(resources, context);
}
}
@ -161,10 +162,10 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
* " entries, but server method response contained " + retVal.size() + " entries (must be the same)"); } }
*/
List<IResource> retResources = retVal.getResources(0, retVal.size());
List<IBaseResource> retResources = retVal.getResources(0, retVal.size());
for (int i = 0; i < retResources.size(); i++) {
IdDt oldId = oldIds.get(retResources.get(i));
IResource newRes = retResources.get(i);
IBaseResource newRes = retResources.get(i);
if (newRes.getId() == null || newRes.getId().isEmpty()) {
if (!(newRes instanceof BaseOperationOutcome)) {
throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)");
@ -172,8 +173,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
}
if (oldId != null && !oldId.isEmpty()) {
if (!oldId.equals(newRes.getId())) {
newRes.getResourceMetadata().put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
if (!oldId.equals(newRes.getId()) && newRes instanceof IResource) {
((IResource)newRes).getResourceMetadata().put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
}
}
}
@ -194,7 +195,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
return new HttpPostClientInvocation(theContext, theBundle);
}
public static BaseHttpClientInvocation createTransactionInvocation(List<IResource> theResources, FhirContext theContext) {
public static BaseHttpClientInvocation createTransactionInvocation(List<IBaseResource> theResources, FhirContext theContext) {
return new HttpPostClientInvocation(theContext, theResources, BundleTypeEnum.TRANSACTION);
}

View File

@ -23,6 +23,8 @@ package ca.uhn.fhir.rest.server;
import java.util.Collections;
import java.util.List;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.InstantDt;
@ -43,7 +45,7 @@ public class BundleProviders {
final InstantDt published = InstantDt.withCurrentTime();
return new IBundleProvider() {
@Override
public List<IResource> getResources(int theFromIndex, int theToIndex) {
public List<IBaseResource> getResources(int theFromIndex, int theToIndex) {
return Collections.emptyList();
}
@ -64,11 +66,11 @@ public class BundleProviders {
};
}
public static IBundleProvider newList(IResource theResource) {
public static IBundleProvider newList(IBaseResource theResource) {
return new SimpleBundleProvider(theResource);
}
public static IBundleProvider newList(List<IResource> theResources) {
public static IBundleProvider newList(List<IBaseResource> theResources) {
return new SimpleBundleProvider(theResources);
}
}

View File

@ -28,6 +28,8 @@ import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -57,7 +59,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
@Override
public void addResourcesToBundle(List<IResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
@ -65,13 +67,14 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
for (IResource next : theResult) {
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
addedResourceIds.add((IdDt) next.getId());
}
}
for (IResource next : theResult) {
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource)nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
@ -152,7 +155,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
int numToReturn;
String searchId = null;
List<IResource> resourceList;
List<IBaseResource> resourceList;
if (theServer.getPagingProvider() == null) {
numToReturn = theResult.size();
resourceList = theResult.getResources(0, numToReturn);
@ -180,7 +183,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
}
}
for (IResource next : resourceList) {
for (IBaseResource next : resourceList) {
if (next.getId() == null || next.getId().isEmpty()) {
if (!(next instanceof BaseOperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
@ -189,7 +192,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
}
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
for (IResource nextRes : resourceList) {
for (IBaseResource nextRes : resourceList) {
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
@ -197,7 +200,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
}
}
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType);
myBundle.setPublished(theResult.getPublished());
@ -261,7 +264,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void initializeBundleFromResourceList(String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
public void initializeBundleFromResourceList(String theAuthor, List<IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
myBundle = new Bundle();
myBundle.getAuthorName().setValue(theAuthor);
@ -271,16 +274,17 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
myBundle.getLinkSelf().setValue(theCompleteUrl);
myBundle.getType().setValueAsEnum(theBundleType);
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
List<IBaseResource> includedResources = new ArrayList<IBaseResource>();
Set<IIdType> addedResourceIds = new HashSet<IIdType>();
for (IResource next : theResult) {
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
}
}
for (IResource next : theResult) {
for (IBaseResource nextRes : theResult) {
IResource next = (IResource) nextRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
@ -301,26 +305,26 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
do {
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
for (BaseResourceReferenceDt nextRef : references) {
IResource nextRes = (IResource) nextRef.getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
IBaseResource nextRefRes = (IBaseResource) nextRef.getResource();
if (nextRefRes != null) {
if (nextRefRes.getId().hasIdPart()) {
if (containedIds.contains(nextRefRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdDt id = nextRes.getId();
IIdType id = nextRefRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRes).getName();
String resName = myContext.getResourceDefinition(nextRefRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
addedResourcesThisPass.add(nextRefRes);
}
}
@ -329,7 +333,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
// Linked resources may themselves have linked resources
references = new ArrayList<BaseResourceReferenceDt>();
for (IResource iResource : addedResourcesThisPass) {
for (IBaseResource iResource : addedResourcesThisPass) {
List<BaseResourceReferenceDt> newReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(iResource, BaseResourceReferenceDt.class);
references.addAll(newReferences);
}
@ -345,8 +349,8 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
/*
* Actually add the resources to the bundle
*/
for (IResource next : includedResources) {
BundleEntry entry = myBundle.addResource(next, myContext, theServerBase);
for (IBaseResource next : includedResources) {
BundleEntry entry = myBundle.addResource((IResource) next, myContext, theServerBase);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
if (entry.getSearchMode().isEmpty()) {
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
@ -358,14 +362,14 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void initializeWithBundleResource(IResource theResource) {
public void initializeWithBundleResource(IBaseResource theResource) {
throw new UnsupportedOperationException("DSTU1 server doesn't support resource style bundles");
}
@Override
public List<IResource> toListOfResources() {
return myBundle.toListOfResources();
public List<IBaseResource> toListOfResources() {
return new ArrayList<IBaseResource>( myBundle.toListOfResources());
}
}

View File

@ -22,7 +22,8 @@ package ca.uhn.fhir.rest.server;
import java.util.List;
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.primitive.InstantDt;
public interface IBundleProvider {
@ -37,7 +38,7 @@ public interface IBundleProvider {
* @param theToIndex The high index (exclusive) to return
* @return A list of resources. The size of this list must be at least <code>theToIndex - theFromIndex</code>.
*/
List<IResource> getResources(int theFromIndex, int theToIndex);
List<IBaseResource> getResources(int theFromIndex, int theToIndex);
/**
* Optionally may be used to signal a preferred page size to the server, e.g. because

View File

@ -23,8 +23,9 @@ package ca.uhn.fhir.rest.server;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
@ -34,7 +35,7 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
*/
public interface IVersionSpecificBundleFactory {
void addResourcesToBundle(List<IResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes);
void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes);
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType);
@ -43,12 +44,12 @@ public interface IVersionSpecificBundleFactory {
Bundle getDstu1Bundle();
IResource getResourceBundle();
IBaseResource getResourceBundle();
void initializeBundleFromResourceList(String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType);
void initializeBundleFromResourceList(String theAuthor, List<IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType);
void initializeWithBundleResource(IResource theResource);
void initializeWithBundleResource(IBaseResource theResource);
List<IResource> toListOfResources();
List<IBaseResource> toListOfResources();
}

View File

@ -27,6 +27,7 @@ import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
@ -39,7 +40,10 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -49,7 +53,6 @@ import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.method.Request;
@ -72,13 +75,13 @@ public class RestfulServerUtils {
return count;
}
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, int stausCode, boolean theRespondGzip, String theServerBase) throws IOException {
theHttpResponse.setStatus(stausCode);
if (theResource.getId() != null && theResource.getId().hasIdPart() && isNotBlank(theServerBase)) {
String resName = theServer.getFhirContext().getResourceDefinition(theResource).getName();
IdDt fullId = theResource.getId().withServerBase(theServerBase, resName);
IIdType fullId = theResource.getId().withServerBase(theServerBase, resName);
theHttpResponse.addHeader(Constants.HEADER_CONTENT_LOCATION, fullId.getValue());
}
@ -130,24 +133,31 @@ public class RestfulServerUtils {
theServer.addHeadersToResponse(theHttpResponse);
InstantDt lastUpdated = ResourceMetadataKeyEnum.UPDATED.get(theResource);
if (lastUpdated != null && lastUpdated.isEmpty() == false) {
theHttpResponse.addHeader(Constants.HEADER_LAST_MODIFIED, DateUtils.formatDate(lastUpdated.getValue()));
}
if (theResource instanceof IResource) {
InstantDt lastUpdated = ResourceMetadataKeyEnum.UPDATED.get((IResource) theResource);
if (lastUpdated != null && lastUpdated.isEmpty() == false) {
theHttpResponse.addHeader(Constants.HEADER_LAST_MODIFIED, DateUtils.formatDate(lastUpdated.getValue()));
}
TagList list = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
theHttpResponse.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
TagList list = (TagList) ((IResource)theResource).getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
theHttpResponse.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
}
}
}
} else {
Date lastUpdated = ((IAnyResource)theResource).getMeta().getLastUpdated();
if (lastUpdated != null) {
theHttpResponse.addHeader(Constants.HEADER_LAST_MODIFIED, DateUtils.formatDate(lastUpdated));
}
}
Writer writer = getWriter(theHttpResponse, theRespondGzip);
try {
if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
writer.append(theResource.getText().getDiv().getValueAsString());
if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY && theResource instanceof IResource) {
writer.append(((IResource)theResource).getText().getDiv().getValueAsString());
} else {
IParser parser = getNewParser(theServer.getFhirContext(), responseEncoding, thePrettyPrint, theNarrativeMode);
parser.setServerBaseUrl(theServerBase);
@ -267,18 +277,19 @@ public class RestfulServerUtils {
}
}
public static void addProfileToBundleEntry(FhirContext theContext, IResource theResource, String theServerBase) {
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
if (theResource instanceof IResource) {
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
if (tl == null) {
tl = new TagList();
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
}
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get(theResource);
if (tl == null) {
tl = new TagList();
ResourceMetadataKeyEnum.TAG_LIST.put(theResource, tl);
}
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
String profile = nextDef.getResourceProfile(theServerBase);
if (isNotBlank(profile)) {
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
String profile = nextDef.getResourceProfile(theServerBase);
if (isNotBlank(profile)) {
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
}
}
}
@ -402,14 +413,14 @@ public class RestfulServerUtils {
}
}
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
boolean theRequestIsBrowser, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, String theServerBase) throws IOException {
int stausCode = 200;
RestfulServerUtils.streamResponseAsResource(theServer, theHttpResponse, theResource, theResponseEncoding, thePrettyPrint, theRequestIsBrowser, theNarrativeMode, stausCode, theRespondGzip,
theServerBase);
}
public static void validateResourceListNotNull(List<IResource> theResourceList) {
public static void validateResourceListNotNull(List<? extends IBaseResource> theResourceList) {
if (theResourceList == null) {
throw new InternalErrorException("IBundleProvider returned a null list of resources - This is not allowed");
}

View File

@ -23,18 +23,19 @@ package ca.uhn.fhir.rest.server;
import java.util.Collections;
import java.util.List;
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.IBaseResource;
import ca.uhn.fhir.model.primitive.InstantDt;
public class SimpleBundleProvider implements IBundleProvider {
private List<IResource> myList;
private List<IBaseResource> myList;
public SimpleBundleProvider(List<IResource> theList) {
public SimpleBundleProvider(List<IBaseResource> theList) {
myList = theList;
}
public SimpleBundleProvider(IResource theResource) {
public SimpleBundleProvider(IBaseResource theResource) {
myList = Collections.singletonList(theResource);
}
@ -46,7 +47,7 @@ public class SimpleBundleProvider implements IBundleProvider {
}
@Override
public List<IResource> getResources(int theFromIndex, int theToIndex) {
public List<IBaseResource> getResources(int theFromIndex, int theToIndex) {
return myList.subList(theFromIndex, Math.min(theToIndex, myList.size()));
}

View File

@ -26,6 +26,7 @@ import java.util.List;
import org.hl7.fhir.instance.model.IBase;
import ca.uhn.fhir.model.api.ICompositeElement;
import ca.uhn.fhir.model.api.IElement;
public class ElementUtil {
@ -62,6 +63,19 @@ public class ElementUtil {
return true;
}
public static boolean isEmpty(IElement... theElements) {
if (theElements == null) {
return true;
}
for (int i = 0; i < theElements.length; i++) {
IBase next = theElements[i];
if (next != null && !next.isEmpty()) {
return false;
}
}
return true;
}
public static boolean isEmpty(List<? extends IBase> theElements) {
if (theElements == null) {
return true;

View File

@ -2,6 +2,8 @@ package org.hl7.fhir.instance.model;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.TagList;
/*
* #%L
* HAPI FHIR - Core Library

View File

@ -0,0 +1,7 @@
package org.hl7.fhir.instance.model.api;
import org.hl7.fhir.instance.model.IBaseResource;
public interface IBaseConformance extends IBaseResource {
}

View File

@ -22,7 +22,7 @@ package org.hl7.fhir.instance.model.api;
import java.util.List;
public interface IDomainResource {
public interface IDomainResource extends IAnyResource {
List<? extends IAnyResource> getContained();

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.instance.model.api;
import ca.uhn.fhir.model.primitive.IdDt;
/*
* #%L
* HAPI FHIR - Core Library
@ -55,4 +57,16 @@ public interface IIdType {
String getVersionIdPart();
IIdType toUnqualified();
boolean hasResourceType();
IIdType withResourceType(String theResName);
String getResourceType();
IIdType withServerBase(String theServerBase, String theResourceName);
boolean isAbsolute();
}

View File

@ -30,4 +30,8 @@ public interface IMetaType extends ICompositeType {
IMetaType setLastUpdated(Date theHeaderDateValue);
Date getLastUpdated();
String getVersionId();
}

View File

@ -1,11 +1,12 @@
package ca.uhn.fhir.parser;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -14,7 +15,6 @@ import org.slf4j.LoggerFactory;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
@ -191,7 +191,7 @@ public class ContainedResourceEncodingTest {
observation.setPerformer(performers);
List<IResource> list = new ArrayList<IResource>();
List<IBaseResource> list = new ArrayList<IBaseResource>();
list.add(dr);
IVersionSpecificBundleFactory factory = ctx.newBundleFactory();
@ -233,7 +233,7 @@ public class ContainedResourceEncodingTest {
observation.setPerformer(performers);
List<IResource> list = new ArrayList<IResource>();
List<IBaseResource> list = new ArrayList<IBaseResource>();
list.add(dr);
IVersionSpecificBundleFactory factory = ctx.newBundleFactory();

View File

@ -687,7 +687,7 @@ public class GenericClientTest {
Bundle response = client.search()
.forResource(Patient.class)
.encodedJson()
.revinclude(Provenance.INCLUDE_TARGET)
.revInclude(Provenance.INCLUDE_TARGET)
.execute();
//@formatter:on

View File

@ -1,26 +1,36 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.*;
import static org.junit.Assert.assertEquals;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.Practitioner;
import ca.uhn.fhir.model.dstu.resource.Specimen;
/**
* Created by Bill de Beaubien on 3/3/2015.
*/
public class Dstu1BundleFactoryTest {
private static FhirContext ourCtx;
private List<IResource> myResourceList;
private List<IBaseResource> myResourceList;
private Dstu1BundleFactory myBundleFactory;
@BeforeClass
@ -71,7 +81,7 @@ public class Dstu1BundleFactoryTest {
specimen1.setSubject(new ResourceReferenceDt(patient));
specimen1.getCollection().setCollector(new ResourceReferenceDt(practitioner));
myResourceList = Arrays.asList(new IResource[]{diagnosticReport});
myResourceList = Arrays.asList(new IBaseResource[]{diagnosticReport});
myBundleFactory = new Dstu1BundleFactory(ourCtx);
}

View File

@ -1,8 +1,13 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
@ -19,6 +24,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@ -284,7 +290,7 @@ public class PagingTest {
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
List<IResource> retVal = new ArrayList<IResource>();
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (int i = 0; i < 10; i++) {
Patient patient = new Patient();
patient.setId("" + i);

View File

@ -1,8 +1,13 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
@ -33,6 +38,7 @@ import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.core.StringContains;
import org.hamcrest.core.StringEndsWith;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@ -95,7 +101,7 @@ public class RestfulServerMethodTest {
@Test
public void testCreateBundleDoesntCreateDoubleEntries() {
List<IResource> resources = new ArrayList<IResource>();
List<IBaseResource> resources = new ArrayList<IBaseResource>();
Patient p = new Patient();
p.setId("Patient/1");

View File

@ -40,7 +40,7 @@
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>1.5</version>
<version>1.6</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -31,9 +31,11 @@ import java.util.UUID;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.server.*;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -63,7 +65,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addResourcesToBundle(List<IResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
@ -71,13 +73,14 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
for (IResource next : theResult) {
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
addedResourceIds.add((IdDt) next.getId());
}
}
for (IResource next : theResult) {
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource) nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
@ -197,7 +200,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
int numToReturn;
String searchId = null;
List<IResource> resourceList;
List<IBaseResource> resourceList;
if (theServer.getPagingProvider() == null) {
numToReturn = theResult.size();
resourceList = theResult.getResources(0, numToReturn);
@ -225,7 +228,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
}
for (IResource next : resourceList) {
for (IBaseResource next : resourceList) {
if (next.getId() == null || next.getId().isEmpty()) {
if (!(next instanceof BaseOperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
@ -234,7 +237,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
for (IResource nextRes : resourceList) {
for (IBaseResource nextRes : resourceList) {
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
@ -242,7 +245,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
}
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType);
if (theServer.getPagingProvider() != null) {
@ -273,7 +276,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void initializeBundleFromResourceList(String theAuthor, List<IResource> theResources, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
public void initializeBundleFromResourceList(String theAuthor, List<IBaseResource> theResources, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
myBundle = new Bundle();
myBundle.setId(UUID.randomUUID().toString());
@ -285,7 +288,8 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
myBundle.getTypeElement().setValueAsString(theBundleType.getCode());
if (theBundleType.equals(BundleTypeEnum.TRANSACTION)) {
for (IResource next : theResources) {
for (IBaseResource nextBaseRes : theResources) {
IResource next = (IResource)nextBaseRes;
Entry nextEntry = myBundle.addEntry();
nextEntry.setResource(next);
@ -308,18 +312,18 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
myBundle.getTotalElement().setValue(theTotalResults);
}
private void addResourcesForSearch(List<IResource> theResult) {
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
private void addResourcesForSearch(List<IBaseResource> theResult) {
List<IBaseResource> includedResources = new ArrayList<IBaseResource>();
Set<IIdType> addedResourceIds = new HashSet<IIdType>();
for (IResource next : theResult) {
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
}
}
for (IResource next : theResult) {
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource)nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
@ -383,19 +387,19 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
/*
* Actually add the resources to the bundle
*/
for (IResource next : includedResources) {
myBundle.addEntry().setResource(next).getSearch().setMode(SearchEntryModeEnum.INCLUDE);
for (IBaseResource next : includedResources) {
myBundle.addEntry().setResource((IResource) next).getSearch().setMode(SearchEntryModeEnum.INCLUDE);
}
}
@Override
public void initializeWithBundleResource(IResource theBundle) {
public void initializeWithBundleResource(IBaseResource theBundle) {
myBundle = (Bundle) theBundle;
}
@Override
public List<IResource> toListOfResources() {
ArrayList<IResource> retVal = new ArrayList<IResource>();
public List<IBaseResource> toListOfResources() {
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (Entry next : myBundle.getEntry()) {
if (next.getResource()!=null) {
retVal.add(next.getResource());

View File

@ -58,6 +58,28 @@ public class JsonParserDstu2Test {
assertEquals("{\"resourceType\":\"Binary\",\"id\":\"11\",\"meta\":{\"versionId\":\"22\"},\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", val);
}
@Test
public void testEncodingNullExtension() {
Patient p = new Patient();
ExtensionDt extension = new ExtensionDt(false, "http://foo#bar");
p.addUndeclaredExtension(extension);
String str = ourCtx.newJsonParser().encodeResourceToString(p);
assertEquals("{\"resourceType\":\"Patient\"}", str);
extension.setValue(new StringDt());
str = ourCtx.newJsonParser().encodeResourceToString(p);
assertEquals("{\"resourceType\":\"Patient\"}", str);
extension.setValue(new StringDt(""));
str = ourCtx.newJsonParser().encodeResourceToString(p);
assertEquals("{\"resourceType\":\"Patient\"}", str);
}
/**
* See #144 and #146
*/

View File

@ -0,0 +1,113 @@
package ca.uhn.fhir.parser;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import org.apache.commons.io.IOUtils;
import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.DifferenceListener;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Test;
import org.w3c.dom.Node;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.XmlUtil;
public class RoundTripDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RoundTripDstu2Test.class);
private static FhirContext ourCtx = FhirContext.forDstu2();
@Test
public void testRoundTrip() throws Exception {
ZipInputStream is = new ZipInputStream(new FileInputStream("src/test/resources/examples.zip"));
try {
while (true) {
ZipEntry nextEntry = is.getNextEntry();
if (nextEntry == null) {
break;
}
ByteArrayOutputStream oos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while ((len = is.read(buffer)) > 0) {
oos.write(buffer, 0, len);
}
String exampleText = oos.toString("UTF-8");
ourLog.info("Next file: {} - Size: {} bytes", nextEntry.getName(), exampleText.length());
if (!nextEntry.getName().contains("diagnosticreport-examples-lab")) {
continue;
}
IBaseResource parsed = ourCtx.newXmlParser().parseResource(exampleText);
String encodedXml = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
exampleText = cleanXml(exampleText);
encodedXml = cleanXml(encodedXml);
DetailedDiff d = new DetailedDiff(new Diff(new StringReader(exampleText), new StringReader(encodedXml)));
// d.overrideDifferenceListener(new DifferenceListener() {
//
// @Override
// public void skippedComparison(Node theControl, Node theTest) {
// ourLog.info("" + theControl);
// }
//
// @Override
// public int differenceFound(Difference theDifference) {
// ourLog.info("" + theDifference);
// return 0;
// }
// });
boolean similar = d.similar();
if (!similar) {
exampleText = exampleText.replace(" xmlns=\"http://hl7.org/fhir\"", "");
encodedXml = encodedXml.replace(" xmlns=\"http://hl7.org/fhir\"", "");
if (exampleText.length() != encodedXml.length()) {
// ourLog.info("Expected: " + exampleText);
// ourLog.info("Actual : " + encodedXml);
assertTrue(d.toString(), similar);
}
}
}
} finally {
is.close();
}
}
private String cleanXml(String exampleText) throws Error, Exception {
XMLEventReader read = XmlUtil.createXmlReader(new StringReader(exampleText));
StringWriter sw = new StringWriter();
XMLEventWriter write = XmlUtil.createXmlWriter(sw);
while (read.hasNext()) {
XMLEvent nextEvent = read.nextEvent();
if (nextEvent.getEventType() == XMLStreamConstants.COMMENT) {
continue;
}
write.add(nextEvent);
}
write.add(read);
sw.close();
return sw.toString().replaceAll("<!--.*-->", "").replace("\n", " ").replace("\r", " ").replaceAll(">\\s+<", "><").replaceAll("<\\?.*\\?>", "").replaceAll("\\s+", " ");
}
}

View File

@ -1,7 +1,16 @@
package ca.uhn.fhir.parser;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.StringReader;
import java.util.ArrayList;
@ -29,12 +38,15 @@ import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
import ca.uhn.fhir.model.dstu2.composite.DurationDt;
import ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt;
import ca.uhn.fhir.model.dstu2.composite.ElementDefinitionDt.Binding;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance;
import ca.uhn.fhir.model.dstu2.resource.Binary;
import ca.uhn.fhir.model.dstu2.resource.Composition;
import ca.uhn.fhir.model.dstu2.resource.DataElement;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.Medication;
import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
@ -60,6 +72,282 @@ public class XmlParserDstu2Test {
XMLUnit.setIgnoreWhitespace(true);
}
@Test
public void testContainedResourceInExtensionUndeclared() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Organization o = new Organization();
o.setName("ORG");
p.addUndeclaredExtension(new ExtensionDt(false, "urn:foo", new ResourceReferenceDt(o)));
String str = ourCtx.newXmlParser().encodeResourceToString(p);
ourLog.info(str);
p = ourCtx.newXmlParser().parseResource(Patient.class, str);
assertEquals("PATIENT", p.getName().get(0).getFamily().get(0).getValue());
List<ExtensionDt> exts = p.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, exts.size());
ResourceReferenceDt rr = (ResourceReferenceDt)exts.get(0).getValue();
o = (Organization) rr.getResource();
assertEquals("ORG", o.getName());
}
@Test
public void testEncodeAndParseExtensionOnResourceReference() {
DataElement de = new DataElement();
Binding b = de.addElement().getBinding();
b.setName("BINDING");
Organization o = new Organization();
o.setName("ORG");
b.addUndeclaredExtension(new ExtensionDt(false, "urn:foo", new ResourceReferenceDt(o)));
String str = ourCtx.newXmlParser().encodeResourceToString(de);
ourLog.info(str);
de = ourCtx.newXmlParser().parseResource(DataElement.class, str);
b = de.getElement().get(0).getBinding();
assertEquals("BINDING", b.getName());
List<ExtensionDt> exts = b.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, exts.size());
ResourceReferenceDt rr = (ResourceReferenceDt)exts.get(0).getValue();
o = (Organization) rr.getResource();
assertEquals("ORG", o.getName());
}
@Test
public void testParseAndEncodeExtensionOnResourceReference() {
//@formatter:off
String input = "<DataElement>" +
"<id value=\"gender\"/>"+
"<contained>"+
"<ValueSet>"+
"<id value=\"2179414\"/>"+
"<url value=\"2179414\"/>"+
"<version value=\"1.0\"/>"+
"<name value=\"Gender Code\"/>"+
"<description value=\"All codes representing the gender of a person.\"/>"+
"<status value=\"active\"/>"+
"<compose>"+
"<include>"+
"<system value=\"http://ncit.nci.nih.gov\"/>"+
"<concept>"+
"<code value=\"C17998\"/>"+
"<display value=\"Unknown\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"C20197\"/>"+
"<display value=\"Male\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"C16576\"/>"+
"<display value=\"Female\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"C38046\"/>"+
"<display value=\"Not specified\"/>"+
"</concept>"+
"</include>"+
"</compose>"+
"</ValueSet>"+
"</contained>"+
"<contained>"+
"<ValueSet>"+
"<id value=\"2179414-permitted\"/>"+
"<status value=\"active\"/>"+
"<define>"+
"<system value=\"http://example.org/fhir/2179414\"/>"+
"<caseSensitive value=\"true\"/>"+
"<concept>"+
"<code value=\"0\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"1\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"2\"/>"+
"</concept>"+
"<concept>"+
"<code value=\"3\"/>"+
"</concept>"+
"</define>"+
"</ValueSet>"+
"</contained>"+
"<contained>"+
"<ConceptMap>"+
"<id value=\"2179414-cm\"/>"+
"<status value=\"active\"/>"+
"<sourceReference>"+
"<reference value=\"#2179414\"/>"+
"</sourceReference>"+
"<targetReference>"+
"<reference value=\"#2179414-permitted\"/>"+
"</targetReference>"+
"<element>"+
"<code value=\"C17998\"/>"+
"<map>"+
"<code value=\"0\"/>"+
"<equivalence value=\"equal\"/>"+
"</map>"+
"</element>"+
"<element>"+
"<code value=\"C20197\"/>"+
"<map>"+
"<code value=\"1\"/>"+
"<equivalence value=\"equal\"/>"+
"</map>"+
"</element>"+
"<element>"+
"<code value=\"C16576\"/>"+
"<map>"+
"<code value=\"2\"/>"+
"<equivalence value=\"equal\"/>"+
"</map>"+
"</element>"+
"<element>"+
"<code value=\"C38046\"/>"+
"<map>"+
"<code value=\"3\"/>"+
"<equivalence value=\"equal\"/>"+
"</map>"+
"</element>"+
"</ConceptMap>"+
"</contained>"+
"<identifier>"+
"<value value=\"2179650\"/>"+
"</identifier>"+
"<version value=\"1.0\"/>"+
"<name value=\"Gender Code\"/>"+
"<useContext>"+
"<coding>"+
"<system value=\"http://example.org/FBPP\"/>"+
"<display value=\"FBPP Pooled Database\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/PhenX\"/>"+
"<display value=\"Demographics\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/EligibilityCriteria\"/>"+
"<display value=\"Pt. Administrative\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/UAMSClinicalResearch\"/>"+
"<display value=\"UAMS New CDEs\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/PhenX\"/>"+
"<display value=\"Substance Abuse and \"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Category\"/>"+
"<display value=\"CSAERS Adverse Event\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/PhenX\"/>"+
"<display value=\"Core: Tier 1\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Category\"/>"+
"<display value=\"Case Report Forms\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Category\"/>"+
"<display value=\"CSAERS Review Set\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Demonstration%20Applications\"/>"+
"<display value=\"CIAF\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/NIDA%20CTN%20Usage\"/>"+
"<display value=\"Clinical Research\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/NIDA%20CTN%20Usage\"/>"+
"<display value=\"Electronic Health Re\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Condition\"/>"+
"<display value=\"Barretts Esophagus\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Condition\"/>"+
"<display value=\"Bladder Cancer\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Condition\"/>"+
"<display value=\"Oral Leukoplakia\"/>"+
"</coding>"+
"<coding>"+
"<system value=\"http://example.org/Condition\"/>"+
"<display value=\"Sulindac for Breast\"/>"+
"</coding>"+
"</useContext>"+
"<status value=\"active\"/>"+
"<publisher value=\"DCP\"/>"+
"<element>"+
"<extension url=\"http://hl7.org/fhir/StructureDefinition/minLength\">"+
"<valueInteger value=\"1\"/>"+
"</extension>"+
"<extension url=\"http://hl7.org/fhir/StructureDefinition/elementdefinition-question\">"+
"<valueString value=\"Gender\"/>"+
"</extension>"+
"<path value=\"Gender\"/>"+
"<definition value=\"The code representing the gender of a person.\"/>"+
"<type>"+
"<code value=\"CodeableConcept\"/>"+
"</type>"+
"<maxLength value=\"13\"/>"+
"<binding>"+
"<name value=\"Gender\"/>"+
"<strength value=\"required\"/>"+
"<valueSetReference>"+
"<extension url=\"http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset\">"+
"<valueReference>"+
"<reference value=\"#2179414-permitted\"/>"+
"</valueReference>"+
"</extension>"+
"<extension url=\"http://hl7.org/fhir/StructureDefinition/11179-permitted-value-conceptmap\">"+
"<valueReference>"+
"<reference value=\"#2179414-cm\"/>"+
"</valueReference>"+
"</extension>"+
"<reference value=\"#2179414\"/>"+
"</valueSetReference>"+
"</binding>"+
"</element>"+
"</DataElement>";
//@formatter:on
DataElement de = ourCtx.newXmlParser().parseResource(DataElement.class, input);
String output = ourCtx.newXmlParser().encodeResourceToString(de).replace(" xmlns=\"http://hl7.org/fhir\"", "");
ElementDefinitionDt elem = de.getElement().get(0);
Binding b = elem.getBinding();
assertEquals("Gender", b.getName());
ResourceReferenceDt ref = (ResourceReferenceDt) b.getValueSet();
assertEquals("#2179414", ref.getReference().getValue());
assertEquals(2, ref.getUndeclaredExtensions().size());
ExtensionDt ext = ref.getUndeclaredExtensions().get(0);
assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset", ext.getUrl());
assertEquals(ResourceReferenceDt.class, ext.getValue().getClass());
assertEquals("#2179414-permitted", ((ResourceReferenceDt)ext.getValue()).getReference().getValue());
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de));
assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset"));
ourLog.info("Expected: {}", input);
ourLog.info("Actual : {}", output);
assertEquals(input, output);
}
@Test
public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary();
@ -71,6 +359,60 @@ public class XmlParserDstu2Test {
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
}
@Test
public void testMoreExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135");
ExtensionDt ext = new ExtensionDt();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.addUndeclaredExtension(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanNameDt name = patient.addName();
name.addFamily("Shmoe");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given"));
given.addUndeclaredExtension(ext2);
StringDt given2 = name.addGiven();
given2.setValue("Shmoe");
ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent");
given2.addUndeclaredExtension(given2ext);
ExtensionDt givenExtChild = new ExtensionDt();
givenExtChild.setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD"));
given2ext.addUndeclaredExtension(givenExtChild);
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt().setUrl("http://example.com#child").setValue(new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt().setUrl("http://example.com#child").setValue(new StringDt("value1"));
parent.addUndeclaredExtension(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(
enc,
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
}
@Test
public void testEncodeNonContained() {

View File

@ -19,6 +19,7 @@ import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@ -64,7 +65,7 @@ public class BundleTypeTest {
p1.addIdentifier().setSystem("urn:system").setValue("value");
IGenericClient client = ourCtx.newRestfulGenericClient("http://foo");
client.transaction().withResources(Arrays.asList((IResource) p1)).execute();
client.transaction().withResources(Arrays.asList((IBaseResource) p1)).execute();
HttpUriRequest value = capt.getValue();

View File

@ -54,7 +54,7 @@ public class ClientServerValidationTestDstu2 {
@Test
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.4.0");
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);

View File

@ -23,6 +23,7 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -34,6 +35,7 @@ import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
@ -42,7 +44,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
public class GenericClientTestDstu2 {
public class GenericClientDstu2Test {
private static FhirContext ourCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
@ -78,7 +80,7 @@ public class GenericClientTestDstu2 {
Bundle response = client.search()
.forResource(Patient.class)
.encodedJson()
.revinclude(ca.uhn.fhir.model.dstu2.resource.Provenance.INCLUDE_TARGET)
.revInclude(new Include("Provenance:target"))
.execute();
//@formatter:on
@ -577,7 +579,7 @@ public class GenericClientTestDstu2 {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
List<IResource> input = new ArrayList<IResource>();
List<IBaseResource> input = new ArrayList<IBaseResource>();
Patient p1 = new Patient(); // No ID
p1.addName().addFamily("PATIENT1");
@ -589,7 +591,7 @@ public class GenericClientTestDstu2 {
input.add(p2);
//@formatter:off
List<IResource> response = client.transaction()
List<IBaseResource> response = client.transaction()
.withResources(input)
.encodedJson()
.execute();

View File

@ -1,7 +1,10 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.List;
@ -20,6 +23,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@ -356,7 +360,7 @@ public class OperationServerTest {
public IBundleProvider opInstanceReturnsBundleProvider() {
ourLastMethod = "$OP_INSTANCE_BUNDLE_PROVIDER";
List<IResource> resources = new ArrayList<IResource>();
List<IBaseResource> resources = new ArrayList<IBaseResource>();
for (int i =0; i < 100;i++) {
Patient p = new Patient();
p.setId("Patient/" + i);

View File

@ -1,23 +1,33 @@
package ca.uhn.fhir.rest.server.provider.dstu2;
import ca.uhn.fhir.rest.server.BundleInclusionRule;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.IBaseResource;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.*;
import static org.junit.Assert.assertEquals;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Specimen;
import ca.uhn.fhir.rest.server.BundleInclusionRule;
public class Dstu2BundleFactoryTest {
private static FhirContext ourCtx;
private List<IResource> myResourceList;
private List<IBaseResource> myResourceList;
private Dstu2BundleFactory myBundleFactory;
@BeforeClass
@ -68,7 +78,7 @@ public class Dstu2BundleFactoryTest {
specimen1.setSubject(new ResourceReferenceDt(patient));
specimen1.getCollection().setCollector(new ResourceReferenceDt(practitioner));
myResourceList = Arrays.asList(new IResource[]{diagnosticReport});
myResourceList = Arrays.asList(new IBaseResource[]{diagnosticReport});
myBundleFactory = new Dstu2BundleFactory(ourCtx);
}

View File

@ -0,0 +1,406 @@
package ca.uhn.fhir.rest.server.provider.dstu2hl7org;
/*
* #%L
* HAPI FHIR Structures - DSTU2 (FHIR v0.4.0)
* %%
* Copyright (C) 2014 - 2015 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.Bundle.BundleLinkComponent;
import org.hl7.fhir.instance.model.Bundle.HttpVerb;
import org.hl7.fhir.instance.model.Bundle.SearchEntryMode;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IdType;
import org.hl7.fhir.instance.model.InstantType;
import org.hl7.fhir.instance.model.OperationOutcome;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IReference;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
import ca.uhn.fhir.rest.server.BundleInclusionRule;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.IPagingProvider;
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ResourceReferenceInfo;
public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
private Bundle myBundle;
private FhirContext myContext;
public Dstu2Hl7OrgBundleFactory(FhirContext theContext) {
myContext = theContext;
}
@Override
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
List<IBaseResource> includedResources = new ArrayList<IBaseResource>();
Set<IIdType> addedResourceIds = new HashSet<IIdType>();
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
}
}
for (IBaseResource nextBaseRes : theResult) {
if (!(nextBaseRes instanceof IDomainResource)) {
continue;
}
IDomainResource next = (IDomainResource) nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IAnyResource nextContained : next.getContained()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
do {
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
for (ResourceReferenceInfo nextRefInfo : references) {
if (!theBundleInclusionRule.shouldIncludeReferencedResource(nextRefInfo, theIncludes))
continue;
IBaseResource nextRes = (IBaseResource) nextRefInfo.getResourceReference().getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdType id = (IdType) nextRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
}
}
}
}
includedResources.addAll(addedResourcesThisPass);
// Linked resources may themselves have linked resources
references = new ArrayList<ResourceReferenceInfo>();
for (IBaseResource iResource : addedResourcesThisPass) {
List<ResourceReferenceInfo> newReferences = myContext.newTerser().getAllResourceReferences(iResource);
references.addAll(newReferences);
}
} while (references.isEmpty() == false);
BundleEntryComponent entry = myBundle.addEntry().setResource((Resource) next);
// BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next);
// if (searchMode != null) {
// entry.getSearch().getModeElement().setValue(searchMode.getCode());
// }
}
/*
* Actually add the resources to the bundle
*/
for (IBaseResource next : includedResources) {
myBundle.addEntry().setResource((Resource) next).getSearch().setMode(SearchEntryMode.INCLUDE);
}
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType) {
if (myBundle.getId().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}
InstantDt published = new InstantDt();
published.setToCurrentTimeInLocalTimeZone();
if (!hasLink(Constants.LINK_SELF, myBundle) && isNotBlank(theCompleteUrl)) {
myBundle.addLink().setRelation("self").setUrl(theCompleteUrl);
}
if (isBlank(myBundle.getBase()) && isNotBlank(theServerBase)) {
myBundle.setBase(theServerBase);
}
if (myBundle.getTypeElement().isEmpty() && theBundleType != null) {
myBundle.getTypeElement().setValueAsString(theBundleType.getCode());
}
if (myBundle.getTotalElement().isEmpty() && theTotalResults != null) {
myBundle.getTotalElement().setValue(theTotalResults);
}
}
private boolean hasLink(String theLinkType, Bundle theBundle) {
for (BundleLinkComponent next : theBundle.getLink()) {
if (theLinkType.equals(next.getRelation())) {
return true;
}
}
return false;
}
@Override
public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
int numToReturn;
String searchId = null;
List<IBaseResource> resourceList;
if (theServer.getPagingProvider() == null) {
numToReturn = theResult.size();
resourceList = theResult.getResources(0, numToReturn);
RestfulServerUtils.validateResourceListNotNull(resourceList);
} else {
IPagingProvider pagingProvider = theServer.getPagingProvider();
if (theLimit == null) {
numToReturn = pagingProvider.getDefaultPageSize();
} else {
numToReturn = Math.min(pagingProvider.getMaximumPageSize(), theLimit);
}
numToReturn = Math.min(numToReturn, theResult.size() - theOffset);
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
RestfulServerUtils.validateResourceListNotNull(resourceList);
if (theSearchId != null) {
searchId = theSearchId;
} else {
if (theResult.size() > numToReturn) {
searchId = pagingProvider.storeResultList(theResult);
Validate.notNull(searchId, "Paging provider returned null searchId");
}
}
}
for (IBaseResource next : resourceList) {
if (next.getId() == null || next.getId().isEmpty()) {
if (!(next instanceof OperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IBaseResource#setId(IdDt) must be called)");
}
}
}
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
for (IBaseResource nextRes : resourceList) {
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
RestfulServerUtils.addProfileToBundleEntry(theServer.getFhirContext(), nextRes, theServerBase);
}
}
}
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType);
if (theServer.getPagingProvider() != null) {
int limit;
limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize();
limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize());
if (searchId != null) {
if (theOffset + numToReturn < theResult.size()) {
myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint));
}
if (theOffset > 0) {
int start = Math.max(0, theOffset - limit);
myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint));
}
}
}
}
@Override
public ca.uhn.fhir.model.api.Bundle getDstu1Bundle() {
return null;
}
@Override
public IBaseResource getResourceBundle() {
return myBundle;
}
@Override
public void initializeBundleFromResourceList(String theAuthor, List<IBaseResource> theResources, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
myBundle = new Bundle();
myBundle.setId(UUID.randomUUID().toString());
myBundle.getMeta().setLastUpdatedElement(InstantType.withCurrentTime());
myBundle.addLink().setRelation(Constants.LINK_FHIR_BASE).setUrl(theServerBase);
myBundle.addLink().setRelation(Constants.LINK_SELF).setUrl(theCompleteUrl);
myBundle.getTypeElement().setValueAsString(theBundleType.getCode());
if (theBundleType.equals(BundleTypeEnum.TRANSACTION)) {
for (IBaseResource nextBaseRes : theResources) {
IBaseResource next = (IBaseResource)nextBaseRes;
BundleEntryComponent nextEntry = myBundle.addEntry();
nextEntry.setResource((Resource) next);
if (next.getId().isEmpty()) {
nextEntry.getTransaction().setMethod(HttpVerb.POST);
} else {
nextEntry.getTransaction().setMethod(HttpVerb.PUT);
if (next.getId().isAbsolute()) {
nextEntry.getTransaction().setUrl(next.getId().getValue());
} else {
String resourceType = myContext.getResourceDefinition(next).getName();
nextEntry.getTransaction().setUrl(new IdType(theServerBase, resourceType, next.getId().getIdPart(), next.getId().getVersionIdPart()).getValue());
}
}
}
} else {
addResourcesForSearch(theResources);
}
myBundle.getTotalElement().setValue(theTotalResults);
}
private void addResourcesForSearch(List<IBaseResource> theResult) {
List<IBaseResource> includedResources = new ArrayList<IBaseResource>();
Set<IIdType> addedResourceIds = new HashSet<IIdType>();
for (IBaseResource next : theResult) {
if (next.getId().isEmpty() == false) {
addedResourceIds.add(next.getId());
}
}
for (IBaseResource nextBaseRes : theResult) {
IDomainResource next = (IDomainResource)nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IBaseResource nextContained : next.getContained()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List<IReference> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, IReference.class);
do {
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
for (IReference nextRef : references) {
IBaseResource nextRes = (IBaseResource) nextRef.getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IIdType id = nextRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
}
}
}
}
// Linked resources may themselves have linked resources
references = new ArrayList<IReference>();
for (IBaseResource iResource : addedResourcesThisPass) {
List<IReference> newReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(iResource, IReference.class);
references.addAll(newReferences);
}
includedResources.addAll(addedResourcesThisPass);
} while (references.isEmpty() == false);
myBundle.addEntry().setResource((Resource) next);
}
/*
* Actually add the resources to the bundle
*/
for (IBaseResource next : includedResources) {
myBundle.addEntry().setResource((Resource) next).getSearch().setMode(SearchEntryMode.INCLUDE);
}
}
@Override
public void initializeWithBundleResource(IBaseResource theBundle) {
myBundle = (Bundle) theBundle;
}
@Override
public List<IBaseResource> toListOfResources() {
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (BundleEntryComponent next : myBundle.getEntry()) {
if (next.getResource()!=null) {
retVal.add(next.getResource());
} else if (next.getTransactionResponse().getLocationElement().isEmpty() == false) {
IdType id = new IdType(next.getTransactionResponse().getLocation());
String resourceType = id.getResourceType();
if (isNotBlank(resourceType)) {
IBaseResource res = (IBaseResource) myContext.getResourceDefinition(resourceType).newInstance();
res.setId(id);
retVal.add(res);
}
}
}
return retVal;
}
}

View File

@ -38,6 +38,7 @@ import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.provider.dstu2hl7org.Dstu2Hl7OrgBundleFactory;
public class FhirDstu2Hl7Org implements IFhirVersion {
@ -109,7 +110,7 @@ public class FhirDstu2Hl7Org implements IFhirVersion {
@Override
public IVersionSpecificBundleFactory newBundleFactory(FhirContext theContext) {
throw new UnsupportedOperationException();
return new Dstu2Hl7OrgBundleFactory(theContext);
}
}

View File

@ -97,7 +97,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
retVal.setPublisher(myPublisher);
retVal.setDateElement(DateTimeType.now());
retVal.setFhirVersion("0.4.0"); // TODO: pull from model
retVal.setFhirVersion("0.5.0"); // TODO: pull from model
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser
// needs to be modified to actually allow it

View File

@ -292,7 +292,8 @@ public class Narrative extends Element implements INarrative {
*/
public void setDivAsString(String theString) throws Exception {
if (StringUtils.isNotBlank(theString)) {
div = new XhtmlParser().parseFragment(theString);
div = new XhtmlNode();
div.setValueAsString(theString);
} else {
div = null;
}
@ -300,7 +301,7 @@ public class Narrative extends Element implements INarrative {
public String getDivAsString() throws Exception {
if (div != null && !div.isEmpty()) {
return new XhtmlComposer().compose(div);
return div.getValueAsString();
} else {
return null;
}

View File

@ -39,11 +39,12 @@ import org.hl7.fhir.instance.model.annotations.SearchParamDefinition;
import org.hl7.fhir.instance.model.annotations.Block;
import org.hl7.fhir.instance.model.annotations.Child;
import org.hl7.fhir.instance.model.annotations.Description;
import org.hl7.fhir.instance.model.api.IBaseParameters;
/**
* This special resource type is used to represent [operation](operations.html] request and response. It has no other use, and there is no RESTful end=point associated with it.
*/
@ResourceDef(name="Parameters", profile="http://hl7.org/fhir/Profile/Parameters")
public class Parameters extends Resource {
public class Parameters extends Resource implements IBaseParameters {
@Block()
public static class ParametersParameterComponent extends BackboneElement {

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.instance.model;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
@ -26,7 +27,7 @@ public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>
@Override
public boolean isEmpty() {
return super.isEmpty() && getValue() == null;
return super.isEmpty() && StringUtils.isBlank(getValueAsString());
}
public PrimitiveType<T> setValue(T theValue) {

View File

@ -132,7 +132,13 @@ public abstract class Resource extends Base implements IAnyResource {
* @param value The logical id of the resource, as used in the url for the resoure. Once assigned, this value never changes.
*/
public Resource setId(IIdType value) {
this.id = (IdType) value;
if (value == null) {
this.id = null;
} else if (value instanceof IdType) {
this.id = (IdType) value;
} else {
this.id = new IdType(value.getValue());
}
return this;
}

View File

@ -72,15 +72,6 @@ public class StringType extends PrimitiveType<String> {
return getValue();
}
/**
* Returns <code>true</code> if this datatype has no extensions, and has either a <code>null</code> value or an empty ("") value.
*/
@Override
public boolean isEmpty() {
boolean retVal = super.isEmpty() && StringUtils.isBlank(getValue());
return retVal;
}
@Override
protected String parse(String theValue) {
return theValue;

View File

@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.IPrimitiveType;
import org.hl7.fhir.instance.model.annotations.DatatypeDef;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
@ -285,6 +286,9 @@ public class XhtmlNode implements IBaseXhtml {
}
public String getValueAsString() {
if (isEmpty()) {
return null;
}
try {
return new XhtmlComposer().compose(this);
} catch (Exception e) {
@ -295,9 +299,30 @@ public class XhtmlNode implements IBaseXhtml {
@Override
public void setValueAsString(String theValue) throws IllegalArgumentException {
this.Attributes = null;
this.childNodes = null;
this.content = null;
this.name = null;
this.nodeType= null;
if (theValue == null) {
return;
}
String val = theValue.trim();
if (StringUtils.isBlank(theValue)) {
return;
}
if (!val.startsWith("<")) {
val = "<div>" + val + "</div>";
}
if (val.startsWith("<?") && val.endsWith("?>")) {
return;
}
try {
// TODO: this is ugly
XhtmlNode fragment = new XhtmlParser().parseFragment(theValue);
XhtmlNode fragment = new XhtmlParser().parseFragment(val);
this.Attributes = fragment.Attributes;
this.childNodes = fragment.childNodes;
this.content = fragment.content;

View File

@ -919,9 +919,10 @@ private boolean elementIsOk(String name) throws Exception {
throw new Exception("Unable to Parse HTML - does not start with tag. Found "+peekChar()+descLoc());
readChar();
String n = readName().toLowerCase();
readToTagEnd();
XhtmlNode result = new XhtmlNode(NodeType.Element);
result.setName(n);
parseAttributes(result);
readToTagEnd();
unwindPoint = null;
List<XhtmlNode> p = new ArrayList<XhtmlNode>();
parseElementInner(result, p);

View File

@ -1,15 +1,18 @@
# This file contains version definitions
resource.Alert=org.hl7.fhir.instance.model.Alert
resource.AllergyIntolerance=org.hl7.fhir.instance.model.AllergyIntolerance
resource.Appointment=org.hl7.fhir.instance.model.Appointment
resource.AppointmentResponse=org.hl7.fhir.instance.model.AppointmentResponse
resource.AuditEvent=org.hl7.fhir.instance.model.AuditEvent
resource.Basic=org.hl7.fhir.instance.model.Basic
resource.Binary=org.hl7.fhir.instance.model.Binary
resource.BodySite=org.hl7.fhir.instance.model.BodySite
resource.Bundle=org.hl7.fhir.instance.model.Bundle
resource.CarePlan=org.hl7.fhir.instance.model.CarePlan
resource.CarePlan2=org.hl7.fhir.instance.model.CarePlan2
resource.Claim=org.hl7.fhir.instance.model.Claim
resource.ClaimResponse=org.hl7.fhir.instance.model.ClaimResponse
resource.ClinicalAssessment=org.hl7.fhir.instance.model.ClinicalAssessment
resource.ClinicalImpression=org.hl7.fhir.instance.model.ClinicalImpression
resource.Communication=org.hl7.fhir.instance.model.Communication
resource.CommunicationRequest=org.hl7.fhir.instance.model.CommunicationRequest
resource.Composition=org.hl7.fhir.instance.model.Composition
@ -36,8 +39,8 @@ resource.EnrollmentRequest=org.hl7.fhir.instance.model.EnrollmentRequest
resource.EnrollmentResponse=org.hl7.fhir.instance.model.EnrollmentResponse
resource.EpisodeOfCare=org.hl7.fhir.instance.model.EpisodeOfCare
resource.ExplanationOfBenefit=org.hl7.fhir.instance.model.ExplanationOfBenefit
resource.ExtensionDefinition=org.hl7.fhir.instance.model.ExtensionDefinition
resource.FamilyHistory=org.hl7.fhir.instance.model.FamilyHistory
resource.FamilyMemberHistory=org.hl7.fhir.instance.model.FamilyMemberHistory
resource.Flag=org.hl7.fhir.instance.model.Flag
resource.Goal=org.hl7.fhir.instance.model.Goal
resource.Group=org.hl7.fhir.instance.model.Group
resource.HealthcareService=org.hl7.fhir.instance.model.HealthcareService
@ -45,8 +48,7 @@ resource.ImagingObjectSelection=org.hl7.fhir.instance.model.ImagingObjectSelecti
resource.ImagingStudy=org.hl7.fhir.instance.model.ImagingStudy
resource.Immunization=org.hl7.fhir.instance.model.Immunization
resource.ImmunizationRecommendation=org.hl7.fhir.instance.model.ImmunizationRecommendation
resource.InstitutionalClaim=org.hl7.fhir.instance.model.InstitutionalClaim
resource.List=org.hl7.fhir.instance.model.List_
resource.List=org.hl7.fhir.instance.model.ListResource
resource.Location=org.hl7.fhir.instance.model.Location
resource.Media=org.hl7.fhir.instance.model.Media
resource.Medication=org.hl7.fhir.instance.model.Medication
@ -60,61 +62,52 @@ resource.NutritionOrder=org.hl7.fhir.instance.model.NutritionOrder
resource.Observation=org.hl7.fhir.instance.model.Observation
resource.OperationDefinition=org.hl7.fhir.instance.model.OperationDefinition
resource.OperationOutcome=org.hl7.fhir.instance.model.OperationOutcome
resource.OralHealthClaim=org.hl7.fhir.instance.model.OralHealthClaim
resource.Order=org.hl7.fhir.instance.model.Order
resource.OrderResponse=org.hl7.fhir.instance.model.OrderResponse
resource.Organization=org.hl7.fhir.instance.model.Organization
resource.Other=org.hl7.fhir.instance.model.Other
resource.Parameters=org.hl7.fhir.instance.model.Parameters
resource.Patient=org.hl7.fhir.instance.model.Patient
resource.PaymentNotice=org.hl7.fhir.instance.model.PaymentNotice
resource.PaymentReconciliation=org.hl7.fhir.instance.model.PaymentReconciliation
resource.PendedRequest=org.hl7.fhir.instance.model.PendedRequest
resource.Person=org.hl7.fhir.instance.model.Person
resource.PharmacyClaim=org.hl7.fhir.instance.model.PharmacyClaim
resource.Practitioner=org.hl7.fhir.instance.model.Practitioner
resource.Procedure=org.hl7.fhir.instance.model.Procedure
resource.ProcedureRequest=org.hl7.fhir.instance.model.ProcedureRequest
resource.ProfessionalClaim=org.hl7.fhir.instance.model.ProfessionalClaim
resource.Profile=org.hl7.fhir.instance.model.Profile
resource.ProcessRequest=org.hl7.fhir.instance.model.ProcessRequest
resource.ProcessResponse=org.hl7.fhir.instance.model.ProcessResponse
resource.Provenance=org.hl7.fhir.instance.model.Provenance
resource.Questionnaire=org.hl7.fhir.instance.model.Questionnaire
resource.QuestionnaireAnswers=org.hl7.fhir.instance.model.QuestionnaireAnswers
resource.Readjudicate=org.hl7.fhir.instance.model.Readjudicate
resource.ReferralRequest=org.hl7.fhir.instance.model.ReferralRequest
resource.RelatedPerson=org.hl7.fhir.instance.model.RelatedPerson
resource.Reversal=org.hl7.fhir.instance.model.Reversal
resource.RiskAssessment=org.hl7.fhir.instance.model.RiskAssessment
resource.Schedule=org.hl7.fhir.instance.model.Schedule
resource.SearchParameter=org.hl7.fhir.instance.model.SearchParameter
resource.SecurityEvent=org.hl7.fhir.instance.model.SecurityEvent
resource.Slot=org.hl7.fhir.instance.model.Slot
resource.Specimen=org.hl7.fhir.instance.model.Specimen
resource.StatusRequest=org.hl7.fhir.instance.model.StatusRequest
resource.StatusResponse=org.hl7.fhir.instance.model.StatusResponse
resource.StructureDefinition=org.hl7.fhir.instance.model.StructureDefinition
resource.Subscription=org.hl7.fhir.instance.model.Subscription
resource.Substance=org.hl7.fhir.instance.model.Substance
resource.Supply=org.hl7.fhir.instance.model.Supply
resource.SupportingDocumentation=org.hl7.fhir.instance.model.SupportingDocumentation
resource.ValueSet=org.hl7.fhir.instance.model.ValueSet
resource.VisionClaim=org.hl7.fhir.instance.model.VisionClaim
resource.VisionPrescription=org.hl7.fhir.instance.model.VisionPrescription
datatype.Address=org.hl7.fhir.instance.model.Address
datatype.Attachment=org.hl7.fhir.instance.model.Attachment
datatype.CodeableConcept=org.hl7.fhir.instance.model.CodeableConcept
datatype.Coding=org.hl7.fhir.instance.model.Coding
datatype.ContactPoint=org.hl7.fhir.instance.model.ContactPoint
datatype.ElementDefinition=org.hl7.fhir.instance.model.ElementDefinition
datatype.HumanName=org.hl7.fhir.instance.model.HumanName
datatype.Identifier=org.hl7.fhir.instance.model.Identifier
datatype.Meta=org.hl7.fhir.instance.model.Meta
datatype.Period=org.hl7.fhir.instance.model.Period
datatype.Quantity=org.hl7.fhir.instance.model.Quantity
datatype.Range=org.hl7.fhir.instance.model.Range
datatype.Ratio=org.hl7.fhir.instance.model.Ratio
datatype.Reference=org.hl7.fhir.instance.model.Reference
datatype.SampledData=org.hl7.fhir.instance.model.SampledData
datatype.Timing=org.hl7.fhir.instance.model.Timing
datatype.Address=org.hl7.fhir.instance.model.AddressType
datatype.Attachment=org.hl7.fhir.instance.model.AttachmentType
datatype.CodeableConcept=org.hl7.fhir.instance.model.CodeableConceptType
datatype.Coding=org.hl7.fhir.instance.model.CodingType
datatype.ContactPoint=org.hl7.fhir.instance.model.ContactPointType
datatype.ElementDefinition=org.hl7.fhir.instance.model.ElementDefinitionType
datatype.HumanName=org.hl7.fhir.instance.model.HumanNameType
datatype.Identifier=org.hl7.fhir.instance.model.IdentifierType
datatype.Meta=org.hl7.fhir.instance.model.MetaType
datatype.Period=org.hl7.fhir.instance.model.PeriodType
datatype.Quantity=org.hl7.fhir.instance.model.QuantityType
datatype.Range=org.hl7.fhir.instance.model.RangeType
datatype.Ratio=org.hl7.fhir.instance.model.RatioType
datatype.SampledData=org.hl7.fhir.instance.model.SampledDataType
datatype.Signature=org.hl7.fhir.instance.model.SignatureType
datatype.Timing=org.hl7.fhir.instance.model.TimingType
datatype.base64Binary=org.hl7.fhir.instance.model.Base64BinaryType
datatype.boolean=org.hl7.fhir.instance.model.BooleanType
datatype.code=org.hl7.fhir.instance.model.CodeType
@ -122,9 +115,13 @@ datatype.date=org.hl7.fhir.instance.model.DateType
datatype.dateTime=org.hl7.fhir.instance.model.DateTimeType
datatype.decimal=org.hl7.fhir.instance.model.DecimalType
datatype.id=org.hl7.fhir.instance.model.IdType
datatype.idref=org.hl7.fhir.instance.model.IdrefType
datatype.instant=org.hl7.fhir.instance.model.InstantType
datatype.integer=org.hl7.fhir.instance.model.IntegerType
datatype.oid=org.hl7.fhir.instance.model.OidType
datatype.positiveInt=org.hl7.fhir.instance.model.PositiveIntType
datatype.string=org.hl7.fhir.instance.model.StringType
datatype.time=org.hl7.fhir.instance.model.TimeType
datatype.unsignedInt=org.hl7.fhir.instance.model.UnsignedIntType
datatype.uri=org.hl7.fhir.instance.model.UriType
datatype.xhtml=org.hl7.fhir.instance.model.XhtmlType

View File

@ -24,6 +24,7 @@ import org.hl7.fhir.instance.model.IntegerType;
import org.hl7.fhir.instance.model.List_;
import org.hl7.fhir.instance.model.Meta;
import org.hl7.fhir.instance.model.Narrative;
import org.hl7.fhir.instance.model.Parameters;
import org.hl7.fhir.instance.model.PrimitiveType;
import org.hl7.fhir.instance.model.Reference;
import org.hl7.fhir.instance.model.Resource;
@ -43,6 +44,7 @@ import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.instance.model.api.ICoding;
import org.hl7.fhir.instance.model.api.IDatatypeElement;
@ -199,6 +201,11 @@ public class ModelInheritanceTest {
assertTrue(IReference.class.isAssignableFrom(Reference.class));
}
@Test
public void testParameters() {
assertTrue(IBaseParameters.class.isAssignableFrom(Parameters.class));
}
@Test
public void testResource() {
assertTrue(IAnyResource.class.isAssignableFrom(Resource.class));

View File

@ -0,0 +1,22 @@
package ca.uhn.fhir.model;
import static org.junit.Assert.*;
import org.hl7.fhir.instance.model.Narrative;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.Test;
public class XhtmlNodeTest {
@Test
public void testNamespaces() {
Narrative type = new Narrative();
XhtmlNode div = type.getDiv();
div.setValue("<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">hello</xhtml:div>");
assertEquals("<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">hello</xhtml:div>", div.getValue());
}
}

View File

@ -5,14 +5,12 @@ import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.nio.charset.Charset;
@ -37,8 +35,6 @@ import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.CodeableConcept;
import org.hl7.fhir.instance.model.Composition;
import org.hl7.fhir.instance.model.Conformance;
import org.hl7.fhir.instance.model.Conformance.ConformanceRestResourceComponent;
import org.hl7.fhir.instance.model.DateTimeType;
import org.hl7.fhir.instance.model.DateType;
import org.hl7.fhir.instance.model.DecimalType;
@ -56,12 +52,10 @@ import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
import org.hl7.fhir.instance.model.Observation;
import org.hl7.fhir.instance.model.Organization;
import org.hl7.fhir.instance.model.Patient;
import org.hl7.fhir.instance.model.Profile;
import org.hl7.fhir.instance.model.Reference;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.Specimen;
import org.hl7.fhir.instance.model.StringType;
import org.hl7.fhir.instance.model.ValueSet;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xml.sax.SAXException;
@ -70,19 +64,298 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredAddressExtension;
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredAddressExtension;
import ca.uhn.fhir.parser.JsonParserHl7OrgTest.MyPatientWithOneDeclaredExtension;
public class XmlParserTest {
public class XmlParserHl7OrgDstu2Test {
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserHl7OrgDstu2Test.class);
@BeforeClass
public static void beforeClass2() {
System.setProperty("file.encoding", "ISO-8859-1");
}
@Test
public void testContainedResourceInExtensionUndeclared() {
Patient p = new Patient();
p.addName().addFamily("PATIENT");
Organization o = new Organization();
o.setName("ORG");
p.addExtension().setUrl("urn:foo").setValue(new Reference(o));
String str = ourCtx.newXmlParser().encodeResourceToString(p);
ourLog.info(str);
p = ourCtx.newXmlParser().parseResource(Patient.class, str);
assertEquals("PATIENT", p.getName().get(0).getFamily().get(0).getValue());
List<Extension> exts = p.getExtension();
assertEquals(1, exts.size());
Reference rr = (Reference)exts.get(0).getValue();
o = (Organization) rr.getResource();
assertEquals("ORG", o.getName());
}
// TODO: uncomment with new model updates
// @Test
// public void testEncodeAndParseExtensionOnResourceReference() {
// DataElement de = new DataElement();
// Binding b = de.addElement().getBinding();
// b.setName("BINDING");
//
// Organization o = new Organization();
// o.setName("ORG");
// b.addUndeclaredExtension(new ExtensionDt(false, "urn:foo", new ResourceReferenceDt(o)));
//
// String str = ourCtx.newXmlParser().encodeResourceToString(de);
// ourLog.info(str);
//
// de = ourCtx.newXmlParser().parseResource(DataElement.class, str);
// b = de.getElement().get(0).getBinding();
// assertEquals("BINDING", b.getName());
//
// List<ExtensionDt> exts = b.getUndeclaredExtensionsByUrl("urn:foo");
// assertEquals(1, exts.size());
// ResourceReferenceDt rr = (ResourceReferenceDt)exts.get(0).getValue();
// o = (Organization) rr.getResource();
// assertEquals("ORG", o.getName());
//
// }
//
// @Test
// public void testParseAndEncodeExtensionOnResourceReference() {
// //@formatter:off
// String input = "<DataElement>" +
// "<id value=\"gender\"/>"+
// "<contained>"+
// "<ValueSet>"+
// "<id value=\"2179414\"/>"+
// "<url value=\"2179414\"/>"+
// "<version value=\"1.0\"/>"+
// "<name value=\"Gender Code\"/>"+
// "<description value=\"All codes representing the gender of a person.\"/>"+
// "<status value=\"active\"/>"+
// "<compose>"+
// "<include>"+
// "<system value=\"http://ncit.nci.nih.gov\"/>"+
// "<concept>"+
// "<code value=\"C17998\"/>"+
// "<display value=\"Unknown\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"C20197\"/>"+
// "<display value=\"Male\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"C16576\"/>"+
// "<display value=\"Female\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"C38046\"/>"+
// "<display value=\"Not specified\"/>"+
// "</concept>"+
// "</include>"+
// "</compose>"+
// "</ValueSet>"+
// "</contained>"+
// "<contained>"+
// "<ValueSet>"+
// "<id value=\"2179414-permitted\"/>"+
// "<status value=\"active\"/>"+
// "<define>"+
// "<system value=\"http://example.org/fhir/2179414\"/>"+
// "<caseSensitive value=\"true\"/>"+
// "<concept>"+
// "<code value=\"0\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"1\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"2\"/>"+
// "</concept>"+
// "<concept>"+
// "<code value=\"3\"/>"+
// "</concept>"+
// "</define>"+
// "</ValueSet>"+
// "</contained>"+
// "<contained>"+
// "<ConceptMap>"+
// "<id value=\"2179414-cm\"/>"+
// "<status value=\"active\"/>"+
// "<sourceReference>"+
// "<reference value=\"#2179414\"/>"+
// "</sourceReference>"+
// "<targetReference>"+
// "<reference value=\"#2179414-permitted\"/>"+
// "</targetReference>"+
// "<element>"+
// "<code value=\"C17998\"/>"+
// "<map>"+
// "<code value=\"0\"/>"+
// "<equivalence value=\"equal\"/>"+
// "</map>"+
// "</element>"+
// "<element>"+
// "<code value=\"C20197\"/>"+
// "<map>"+
// "<code value=\"1\"/>"+
// "<equivalence value=\"equal\"/>"+
// "</map>"+
// "</element>"+
// "<element>"+
// "<code value=\"C16576\"/>"+
// "<map>"+
// "<code value=\"2\"/>"+
// "<equivalence value=\"equal\"/>"+
// "</map>"+
// "</element>"+
// "<element>"+
// "<code value=\"C38046\"/>"+
// "<map>"+
// "<code value=\"3\"/>"+
// "<equivalence value=\"equal\"/>"+
// "</map>"+
// "</element>"+
// "</ConceptMap>"+
// "</contained>"+
// "<identifier>"+
// "<value value=\"2179650\"/>"+
// "</identifier>"+
// "<version value=\"1.0\"/>"+
// "<name value=\"Gender Code\"/>"+
// "<useContext>"+
// "<coding>"+
// "<system value=\"http://example.org/FBPP\"/>"+
// "<display value=\"FBPP Pooled Database\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/PhenX\"/>"+
// "<display value=\"Demographics\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/EligibilityCriteria\"/>"+
// "<display value=\"Pt. Administrative\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/UAMSClinicalResearch\"/>"+
// "<display value=\"UAMS New CDEs\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/PhenX\"/>"+
// "<display value=\"Substance Abuse and \"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Category\"/>"+
// "<display value=\"CSAERS Adverse Event\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/PhenX\"/>"+
// "<display value=\"Core: Tier 1\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Category\"/>"+
// "<display value=\"Case Report Forms\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Category\"/>"+
// "<display value=\"CSAERS Review Set\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Demonstration%20Applications\"/>"+
// "<display value=\"CIAF\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/NIDA%20CTN%20Usage\"/>"+
// "<display value=\"Clinical Research\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/NIDA%20CTN%20Usage\"/>"+
// "<display value=\"Electronic Health Re\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Condition\"/>"+
// "<display value=\"Barretts Esophagus\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Condition\"/>"+
// "<display value=\"Bladder Cancer\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Condition\"/>"+
// "<display value=\"Oral Leukoplakia\"/>"+
// "</coding>"+
// "<coding>"+
// "<system value=\"http://example.org/Condition\"/>"+
// "<display value=\"Sulindac for Breast\"/>"+
// "</coding>"+
// "</useContext>"+
// "<status value=\"active\"/>"+
// "<publisher value=\"DCP\"/>"+
// "<element>"+
// "<extension url=\"http://hl7.org/fhir/StructureDefinition/minLength\">"+
// "<valueInteger value=\"1\"/>"+
// "</extension>"+
// "<extension url=\"http://hl7.org/fhir/StructureDefinition/elementdefinition-question\">"+
// "<valueString value=\"Gender\"/>"+
// "</extension>"+
// "<path value=\"Gender\"/>"+
// "<definition value=\"The code representing the gender of a person.\"/>"+
// "<type>"+
// "<code value=\"CodeableConcept\"/>"+
// "</type>"+
// "<maxLength value=\"13\"/>"+
// "<binding>"+
// "<name value=\"Gender\"/>"+
// "<strength value=\"required\"/>"+
// "<valueSetReference>"+
// "<extension url=\"http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset\">"+
// "<valueReference>"+
// "<reference value=\"#2179414-permitted\"/>"+
// "</valueReference>"+
// "</extension>"+
// "<extension url=\"http://hl7.org/fhir/StructureDefinition/11179-permitted-value-conceptmap\">"+
// "<valueReference>"+
// "<reference value=\"#2179414-cm\"/>"+
// "</valueReference>"+
// "</extension>"+
// "<reference value=\"#2179414\"/>"+
// "</valueSetReference>"+
// "</binding>"+
// "</element>"+
// "</DataElement>";
// //@formatter:on
// DataElement de = ourCtx.newXmlParser().parseResource(DataElement.class, input);
// String output = ourCtx.newXmlParser().encodeResourceToString(de).replace(" xmlns=\"http://hl7.org/fhir\"", "");
//
// ElementDefinitionDt elem = de.getElement().get(0);
// Binding b = elem.getBinding();
// assertEquals("Gender", b.getName());
//
// ResourceReferenceDt ref = (ResourceReferenceDt) b.getValueSet();
// assertEquals("#2179414", ref.getReference().getValue());
//
// assertEquals(2, ref.getUndeclaredExtensions().size());
// ExtensionDt ext = ref.getUndeclaredExtensions().get(0);
// assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset", ext.getUrl());
// assertEquals(ResourceReferenceDt.class, ext.getValue().getClass());
// assertEquals("#2179414-permitted", ((ResourceReferenceDt)ext.getValue()).getReference().getValue());
//
// ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de));
//
// assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset"));
//
// ourLog.info("Expected: {}", input);
// ourLog.info("Actual : {}", output);
// assertEquals(input, output);
// }
@Test
public void testEncodeBinaryWithNoContentType() {
Binary b = new Binary();
@ -94,6 +367,80 @@ public class XmlParserTest {
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\"><content value=\"AQIDBA==\"/></Binary>", output);
}
@Test
public void testMoreExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
Extension ext = new Extension();
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.getExtension().add(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanName name = patient.addName();
name.addFamily("Shmoe");
StringType given = name.addGivenElement();
given.setValue("Joe");
Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
given.getExtension().add(ext2);
StringType given2 = name.addGivenElement();
given2.setValue("Shmoe");
Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
given2.getExtension().add(given2ext);
given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"));
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
Extension parent = new Extension().setUrl("http://example.com#parent");
patient.getExtension().add(parent);
Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
parent.getExtension().add(child1);
Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
parent.getExtension().add(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(
enc,
containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
}
@Test
public void testEncodingNullExtension() {
Patient p = new Patient();
Extension extension = new Extension().setUrl("http://foo#bar");
p.getExtension().add(extension);
String str = ourCtx.newXmlParser().encodeResourceToString(p);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"/>", str);
extension.setValue(new StringType());
str = ourCtx.newXmlParser().encodeResourceToString(p);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"/>", str);
extension.setValue(new StringType(""));
str = ourCtx.newXmlParser().encodeResourceToString(p);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"/>", str);
}
@Test
public void testEncodeNonContained() {
// Create an organization
@ -341,14 +688,18 @@ public class XmlParserTest {
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(bundleString);
List<String> strings = new ArrayList<String>();
strings.addAll(Arrays.asList("<published>", pub.getValueAsString(), "</published>"));
strings.add("<category term=\"http://hl7.org/fhir/tag/message\" label=\"Message\" scheme=\"http://hl7.org/fhir/tag\"/>");
strings.addAll(Arrays.asList("<entry>", "<id>1</id>", "</Patient>", "<summary type=\"xhtml\">", "<div", "</entry>"));
strings.addAll(Arrays.asList("<entry>", "<id>2</id>", "<link rel=\"alternate\" href=\"http://foo/bar\"/>", "<link rel=\"search\" href=\"http://foo/bar/search\"/>", "</entry>"));
assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings));
assertThat(bundleString, not(containsString("at:by")));
//@formatter:on
String[] strings = {
"<Bundle xmlns=\"http://hl7.org/fhir\">",
"<lastUpdated value=\"" + pub.getValueAsString() + "\"/>",
"<Patient xmlns=\"http://hl7.org/fhir\">",
"<id value=\"1\"/>",
"<Patient xmlns=\"http://hl7.org/fhir\">",
"<id value=\"2\"/>"
};
//@formatter:off
assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings));
}
@Test
@ -362,7 +713,13 @@ public class XmlParserTest {
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<category term=\"term\" label=\"label\" scheme=\"scheme\"/>"));
//@formatter:off
assertThat(val, stringContainsInOrder("<tag>",
"<system value=\"scheme\"/>",
"<code value=\"term\"/>",
"<display value=\"label\"/>",
"</tag>"));
//@formatter:on
b = ourCtx.newXmlParser().parseResource(Bundle.class, val);
assertEquals(1, b.getEntry().size());
@ -370,8 +727,6 @@ public class XmlParserTest {
assertEquals("scheme", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getSystem());
assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode());
assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay());
assertNull(b.getEntry().get(0).getResource());
}
@Test
@ -433,7 +788,7 @@ public class XmlParserTest {
int idx = str.indexOf("reference value=\"#") + "reference value=\"#".length();
int idx2 = str.indexOf('"', idx + 1);
String id = str.substring(idx, idx2);
assertThat(str, StringContains.containsString("<Specimen xmlns=\"http://hl7.org/fhir\" id=\"" + id + "\">"));
assertThat(str, stringContainsInOrder("<Specimen xmlns=\"http://hl7.org/fhir\">", "<id value=\"" + id + "\"/>"));
assertThat(str, IsNot.not(StringContains.containsString("<?xml version='1.0'?>")));
}
@ -467,12 +822,12 @@ public class XmlParserTest {
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueReference><reference value=\"Organization/123\"/></valueReference></extension>"));
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse());
Reference ref = actual.getFoo();
assertEquals("Organization/123", ref.getReference());
assertEquals("Organization/123", ref.getReference().getValue());
}
@ -1016,13 +1371,7 @@ public class XmlParserTest {
ourLog.info(str);
assertThat(str, stringContainsInOrder(Arrays.asList("<text value=\"B\"/>", "<text value=\"C\"/>", "<text value=\"A\"/>")));
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>")));
// Only one (outer) contained block
int idx0 = str.indexOf("<contained>");
int idx1 = str.indexOf("<contained>", idx0 + 1);
assertNotEquals(-1, idx0);
assertEquals(-1, idx1);
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>", "<contained>", "</contained>")));
Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
assertEquals("A", obs.getCode().getText());
@ -1038,35 +1387,12 @@ public class XmlParserTest {
@Test
public void testParseBinaryResource() {
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\"><contentType value=\"foo\"/><content value=\"AQIDBA==\"/></Binary>");
assertEquals("foo", val.getContentType());
assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent());
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, str);
assertEquals(Patient.class, b.getEntry().get(0).getResource().getClass());
assertEquals(Patient.class, b.getEntry().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntry().get(2).getResource().getClass());
}
@Test
public void testParseContainedResources() throws IOException {
String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/contained-diagnosticreport.xml"));
IParser p = ourCtx.newXmlParser();
DiagnosticReport bundle = p.parseResource(DiagnosticReport.class, msg);
Reference result0 = bundle.getResult().get(0);
Observation obs = (Observation) result0.getResource();
assertNotNull(obs);
assertEquals("718-7", obs.getCode().getCoding().get(0).getCode());
}
@Test
public void testParseEncodeNarrative() {
@ -1088,18 +1414,6 @@ public class XmlParserTest {
}
/**
* This sample has extra elements in <searchParam> that are not actually a part of the spec any more..
*/
@Test
public void testParseFuroreMetadataWithExtraElements() throws IOException {
String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml"));
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Conformance conf = p.parseResource(Conformance.class, msg);
ConformanceRestResourceComponent res = conf.getRest().get(0).getResource().get(0);
assertEquals("_id", res.getSearchParam().get(1).getName());
}
@Test
public void testParseLanguage() {

View File

@ -0,0 +1,79 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.Patient;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.server.Constants;
public class BundleTypeTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BundleTypeTest.class);
private FhirContext ourCtx;
private HttpClient ourHttpClient;
private HttpResponse ourHttpResponse;
@Before
public void before() {
ourCtx = FhirContext.forDstu2Hl7Org();
ourHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
ourCtx.getRestfulClientFactory().setHttpClient(ourHttpClient);
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
ourHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
@Test
public void testTransaction() throws Exception {
String retVal = ourCtx.newXmlParser().encodeBundleToString(new Bundle());
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")));
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("value");
IGenericClient client = ourCtx.newRestfulGenericClient("http://foo");
client.transaction().withResources(Arrays.asList((IBaseResource) p1)).execute();
HttpUriRequest value = capt.getValue();
assertTrue("Expected request of type POST on long params list", value instanceof HttpPost);
HttpPost post = (HttpPost) value;
String body = IOUtils.toString(post.getEntity().getContent());
IOUtils.closeQuietly(post.getEntity().getContent());
ourLog.info(body);
assertThat(body, Matchers.containsString("<type value=\"" + BundleTypeEnum.TRANSACTION.getCode()));
}
}

View File

@ -0,0 +1,157 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.instance.model.Conformance;
import org.hl7.fhir.instance.model.Patient;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
import ca.uhn.fhir.rest.server.Constants;
public class ClientServerValidationTestDstu2 {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationTestDstu2.class);
private FhirContext myCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
private boolean myFirstResponse;
@Before
public void before() {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
myCtx = FhirContext.forDstu2Hl7Org();
myCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
myFirstResponse = true;
}
@Test
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse=false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}});
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}
@Test
public void testServerReturnsAppropriateVersionForDstu2_050() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse=false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}});
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}
@Test
public void testServerReturnsWrongVersionForDstu2() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.80");
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
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(msg), Charset.forName("UTF-8")));
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
try {
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
fail();
} catch (FhirClientConnectionException e) {
String out = e.toString();
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.80\" which corresponds to DSTU1, but this client is configured to use DSTU2_HL7ORG (via the FhirContext)";
ourLog.info(out);
ourLog.info(want);
assertThat(out, containsString(want));
}
}
}

View File

@ -0,0 +1,280 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.StringReader;
import java.nio.charset.Charset;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.instance.model.Patient;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class ETagClientTest {
private static FhirContext ourCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
@Before
public void before() {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
private String getResourceResult() {
//@formatter:off
String msg =
"<Patient xmlns=\"http://hl7.org/fhir\">"
+ "<id value=\"123\"/>"
+ "<meta>"
+ "<versionId value=\"4444\"/>"
+ "</meta>"
+ "<text><status value=\"generated\" /><div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div></text>"
+ "<identifier><label value=\"SSN\" /><system value=\"http://orionhealth.com/mrn\" /><value value=\"PRP1660\" /></identifier>"
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
+ "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>"
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
+ "<gender value=\"male\"/>"
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
+ "</Patient>";
//@formatter:on
return msg;
}
private Patient getResource() {
return ourCtx.newXmlParser().parseResource(Patient.class, getResourceResult());
}
@Test
public void testReadWithContentLocationInResponse() throws Exception {
String msg = getResourceResult();
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
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(msg), Charset.forName("UTF-8")));
//@formatter:off
Header[] headers = new Header[] {
new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
new BasicHeader(Constants.HEADER_ETAG, "\"9999\"")
};
//@formatter:on
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
Patient response = client.read(Patient.class, new IdDt("Patient/1234"));
assertEquals("http://foo.com/Patient/123/_history/2333", response.getId().getValue());
}
@Test
public void testReadWithIfNoneMatch() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_304_NOT_MODIFIED, "Not modified"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int count = 0;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
try {
client
.read()
.resource(Patient.class)
.withId(new IdDt("Patient/1234"))
.execute();
fail();
} catch (NotModifiedException e) {
// good!
}
//@formatter:on
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
count++;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
Patient expected = new Patient();
Patient response = client
.read()
.resource(Patient.class)
.withId(new IdDt("Patient/1234"))
.ifVersionMatches("9876").returnResource(expected)
.execute();
//@formatter:on
assertSame(expected, response);
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
assertEquals("\"9876\"", capt.getAllValues().get(count).getHeaders(Constants.HEADER_IF_NONE_MATCH_LC)[0].getValue());
count++;
}
@Test
public void testUpdateWithIfMatch() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_200_OK, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int count = 0;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
client
.update()
.resource(getResource())
.withId(new IdDt("Patient/1234"))
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
assertEquals(0, capt.getAllValues().get(count).getHeaders(Constants.HEADER_IF_MATCH_LC).length);
count++;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
client
.update()
.resource(getResource())
.withId(new IdDt("Patient/1234/_history/9876"))
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
assertEquals("\"9876\"", capt.getAllValues().get(count).getHeaders(Constants.HEADER_IF_MATCH_LC)[0].getValue());
count++;
}
@Test
public void testUpdateWithIfMatchWithPreconditionFailed() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_412_PRECONDITION_FAILED, "Precondition Failed"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int count = 0;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
try {
client
.update()
.resource(getResource())
.withId(new IdDt("Patient/1234/_history/9876"))
.execute();
fail();
} catch (PreconditionFailedException e) {
// good
}
//@formatter:on
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
assertEquals("\"9876\"", capt.getAllValues().get(count).getHeaders(Constants.HEADER_IF_MATCH_LC)[0].getValue());
count++;
//@formatter:off
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("")));
try {
Patient resource = getResource();
resource.setId(new IdDt("Patient/1234/_history/9876"));
client
.update()
.resource(resource)
.execute();
fail();
} catch (PreconditionFailedException e) {
// good
}
//@formatter:on
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count).getURI().toString());
assertEquals("\"9876\"", capt.getAllValues().get(count).getHeaders(Constants.HEADER_IF_MATCH_LC)[0].getValue());
count++;
}
@Test
public void testReadWithETag() throws Exception {
String msg = getResourceResult();
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
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(msg), Charset.forName("UTF-8")));
Header[] headers = new Header[] { new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"), new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
new BasicHeader(Constants.HEADER_CATEGORY, "http://foo/tagdefinition.html; scheme=\"http://hl7.org/fhir/tag\"; label=\"Some tag\"") };
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int count = 0;
Patient response = client.read().resource(Patient.class).withId(new IdDt("Patient/1234")).execute();
assertThat(response.getName().get(0).getFamily().get(0).getValue(), StringContains.containsString("Cardinal"));
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count++).getURI().toString());
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
response = (Patient) client.read().resource("Patient").withId("1234").execute();
assertThat(response.getName().get(0).getFamily().get(0).getValue(), StringContains.containsString("Cardinal"));
assertEquals("http://example.com/fhir/Patient/1234", capt.getAllValues().get(count++).getURI().toString());
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
response = client.read().resource(Patient.class).withIdAndVersion("1234", "22").execute();
assertThat(response.getName().get(0).getFamily().get(0).getValue(), StringContains.containsString("Cardinal"));
assertEquals("http://example.com/fhir/Patient/1234/_history/22", capt.getAllValues().get(count++).getURI().toString());
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
response = client.read().resource(Patient.class).withUrl("http://foo/Patient/22").execute();
assertThat(response.getName().get(0).getFamily().get(0).getValue(), StringContains.containsString("Cardinal"));
assertEquals("http://foo/Patient/22", capt.getAllValues().get(count++).getURI().toString());
}
@BeforeClass
public static void beforeClass() {
ourCtx = new FhirContext();
}
}

View File

@ -0,0 +1,813 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.IdType;
import org.hl7.fhir.instance.model.Parameters;
import org.hl7.fhir.instance.model.Patient;
import org.hl7.fhir.instance.model.StringType;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
public class GenericClientDstu2Hl7OrgTest {
private static FhirContext ourCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
@BeforeClass
public static void beforeClass() {
ourCtx = FhirContext.forDstu2Hl7Org();
}
@Before
public void before() {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
@SuppressWarnings("unused")
@Test
public void testSearchWithReverseInclude() throws Exception {
String msg = getPatientFeedWithOneResult();
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
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(msg), Charset.forName("UTF-8")));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
//@formatter:off
org.hl7.fhir.instance.model.Bundle response = client.search()
.forResource(Patient.class)
.encodedJson()
.revInclude(new Include("Provenance:target"))
.returnBundle(org.hl7.fhir.instance.model.Bundle.class)
.execute();
//@formatter:on
assertEquals(
"http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json",
capt.getValue().getURI().toString());
}
private String getPatientFeedWithOneResult() {
//@formatter:off
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
"<id>d039f91a-cc3c-4013-988e-af4d8d0614bd</id>\n" +
"<entry>\n" +
"<resource>"
+ "<Patient>"
+ "<text><status value=\"generated\" /><div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div></text>"
+ "<identifier><label value=\"SSN\" /><system value=\"http://orionhealth.com/mrn\" /><value value=\"PRP1660\" /></identifier>"
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
+ "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>"
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
+ "</Patient>"
+ "</resource>\n"
+ " </entry>\n"
+ "</Bundle>";
//@formatter:on
return msg;
}
@Test
public void testHistory() throws Exception {
final String msg = getPatientFeedWithOneResult();
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
org.hl7.fhir.instance.model.Bundle response;
//@formatter:off
response = client
.history()
.onServer()
.andReturnBundle(org.hl7.fhir.instance.model.Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/_history", capt.getAllValues().get(idx).getURI().toString());
assertEquals(1, response.getEntry().size());
idx++;
//@formatter:off
response = client
.history()
.onType(Patient.class)
.andReturnBundle(org.hl7.fhir.instance.model.Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/_history", capt.getAllValues().get(idx).getURI().toString());
assertEquals(1, response.getEntry().size());
idx++;
//@formatter:off
response = client
.history()
.onInstance(new IdType("Patient", "123"))
.andReturnBundle(org.hl7.fhir.instance.model.Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/_history", capt.getAllValues().get(idx).getURI().toString());
assertEquals(1, response.getEntry().size());
idx++;
}
@Test
public void testSearchByString() throws Exception {
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
//@formatter:off
org.hl7.fhir.instance.model.Bundle response = client.search()
.forResource("Patient")
.where(new StringClientParam("name").matches().value("james"))
.returnBundle(org.hl7.fhir.instance.model.Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString());
assertEquals(Patient.class, response.getEntry().get(0).getResource().getClass());
}
@SuppressWarnings("unused")
@Test
public void testSearchRequiresBundleType() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
//@formatter:off
Bundle response = client.search()
.forResource("Patient")
.where(new StringClientParam("name").matches().value("james"))
.execute();
//@formatter:on
fail();
} catch (IllegalArgumentException e) {
// good
}
}
@Test
public void testOperationWithListOfParameterResponse() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
inParams.addParameter().setValue(new StringType("STRINGVALIN1"));
inParams.addParameter().setValue(new StringType("STRINGVALIN2"));
String reqString = p.encodeResourceToString(inParams);
Parameters outParams = new Parameters();
outParams.addParameter().setValue(new StringType("STRINGVALOUT1"));
outParams.addParameter().setValue(new StringType("STRINGVALOUT2"));
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onType(Patient.class)
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onInstance(new IdType("Patient", "123"))
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
resp = client.operation().onInstance(new IdType("http://foo.com/bar/baz/Patient/123/_history/22")).named("$SOMEOPERATION").withParameters(inParams).execute();
// @formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
idx++;
}
@Test
public void testOperationWithNoInParameters() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
final String reqString = p.encodeResourceToString(inParams);
Parameters outParams = new Parameters();
outParams.addParameter().setValue(new StringType("STRINGVALOUT1"));
outParams.addParameter().setValue(new StringType("STRINGVALOUT2"));
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class).execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onType(Patient.class)
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onInstance(new IdType("Patient", "123"))
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
// @formatter:off
resp = client
.operation()
.onInstance(new IdType("http://foo.com/bar/baz/Patient/123/_history/22"))
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class)
.execute();
// @formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
idx++;
}
@Test
public void testOperationAsGetWithNoInParameters() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters outParams = new Parameters();
outParams.addParameter().setValue(new StringType("STRINGVALOUT1"));
outParams.addParameter().setValue(new StringType("STRINGVALOUT2"));
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onType(Patient.class)
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onInstance(new IdType("Patient", "123"))
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
// @formatter:off
resp = client
.operation()
.onInstance(new IdType("http://foo.com/bar/baz/Patient/123/_history/22"))
.named("$SOMEOPERATION")
.withNoParameters(Parameters.class)
.useHttpGet()
.execute();
// @formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
idx++;
}
@Test
public void testOperationAsGetWithInParameters() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
inParams.addParameter().setName("param1").setValue(new StringType("STRINGVALIN1"));
inParams.addParameter().setName("param1").setValue(new StringType("STRINGVALIN1b"));
inParams.addParameter().setName("param2").setValue(new StringType("STRINGVALIN2"));
Parameters outParams = new Parameters();
outParams.addParameter().setValue(new StringType("STRINGVALOUT1"));
outParams.addParameter().setValue(new StringType("STRINGVALOUT2"));
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameters(inParams)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION?param1=STRINGVALIN1&param1=STRINGVALIN1b&param2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onType(Patient.class)
.named("$SOMEOPERATION")
.withParameters(inParams)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION?param1=STRINGVALIN1&param1=STRINGVALIN1b&param2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onInstance(new IdType("Patient", "123"))
.named("$SOMEOPERATION")
.withParameters(inParams)
.useHttpGet()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1&param1=STRINGVALIN1b&param2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
// @formatter:off
resp = client
.operation()
.onInstance(new IdType("http://foo.com/bar/baz/Patient/123/_history/22"))
.named("$SOMEOPERATION")
.withParameters(inParams)
.useHttpGet()
.execute();
// @formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1&param1=STRINGVALIN1b&param2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString());
idx++;
}
@Test
public void testOperationWithBundleResponse() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
inParams.addParameter().setValue(new StringType("STRINGVALIN1"));
inParams.addParameter().setValue(new StringType("STRINGVALIN2"));
String reqString = p.encodeResourceToString(inParams);
org.hl7.fhir.instance.model.Bundle outParams = new org.hl7.fhir.instance.model.Bundle();
outParams.setTotal(123);
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals(1, resp.getParameter().size());
assertEquals(org.hl7.fhir.instance.model.Bundle.class, resp.getParameter().get(0).getResource().getClass());
idx++;
}
@Test
public void testTransactionWithListOfResources() throws Exception {
org.hl7.fhir.instance.model.Bundle resp = new org.hl7.fhir.instance.model.Bundle();
resp.addEntry().getTransactionResponse().setLocation("Patient/1/_history/1");
resp.addEntry().getTransactionResponse().setLocation("Patient/2/_history/2");
String respString = ourCtx.newJsonParser().encodeResourceToString(resp);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
List<IBaseResource> input = new ArrayList<IBaseResource>();
Patient p1 = new Patient(); // No ID
p1.addName().addFamily("PATIENT1");
input.add(p1);
Patient p2 = new Patient(); // Yes ID
p2.addName().addFamily("PATIENT2");
p2.setId("Patient/2");
input.add(p2);
//@formatter:off
List<IBaseResource> response = client.transaction()
.withResources(input)
.encodedJson()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString());
assertEquals(2, response.size());
String requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
org.hl7.fhir.instance.model.Bundle requestBundle = ourCtx.newJsonParser().parseResource(org.hl7.fhir.instance.model.Bundle.class, requestString);
assertEquals(2, requestBundle.getEntry().size());
assertEquals("POST", requestBundle.getEntry().get(0).getTransaction().getMethod().name());
assertEquals("PUT", requestBundle.getEntry().get(1).getTransaction().getMethod().name());
assertEquals("Patient/2", requestBundle.getEntry().get(1).getTransaction().getUrl());
p1 = (Patient) response.get(0);
assertEquals(new IdType("Patient/1/_history/1"), p1.getId().toUnqualified());
// assertEquals("PATIENT1", p1.getName().get(0).getFamily().get(0).getValue());
p2 = (Patient) response.get(1);
assertEquals(new IdType("Patient/2/_history/2"), p2.getId().toUnqualified());
// assertEquals("PATIENT2", p2.getName().get(0).getFamily().get(0).getValue());
}
@Test
public void testTransactionWithTransactionResource() throws Exception {
org.hl7.fhir.instance.model.Bundle resp = new org.hl7.fhir.instance.model.Bundle();
resp.addEntry().getTransactionResponse().setLocation("Patient/1/_history/1");
resp.addEntry().getTransactionResponse().setLocation("Patient/2/_history/2");
String respString = ourCtx.newJsonParser().encodeResourceToString(resp);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")));
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
org.hl7.fhir.instance.model.Bundle input = new org.hl7.fhir.instance.model.Bundle();
Patient p1 = new Patient(); // No ID
p1.addName().addFamily("PATIENT1");
input.addEntry().setResource(p1);
Patient p2 = new Patient(); // Yes ID
p2.addName().addFamily("PATIENT2");
p2.setId("Patient/2");
input.addEntry().setResource(p2);
//@formatter:off
org.hl7.fhir.instance.model.Bundle response = client.transaction()
.withBundle(input)
.encodedJson()
.execute();
//@formatter:on
assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString());
assertEquals(2, response.getEntry().size());
assertEquals("Patient/1/_history/1", response.getEntry().get(0).getTransactionResponse().getLocation());
assertEquals("Patient/2/_history/2", response.getEntry().get(1).getTransactionResponse().getLocation());
}
@Test
public void testDeleteConditional() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
// when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type",
// Constants.CT_TEXT + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
client.delete().resourceById(new IdType("Patient/123")).execute();
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.delete().resourceConditionalByUrl("Patient?name=foo").execute();
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.delete().resourceConditionalByType("Patient").where(new StringClientParam("name").matches().value("foo")).execute();
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
idx++;
}
@Test
public void testCreateConditional() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Patient p = new Patient();
p.addName().addFamily("FOOFAMILY");
client.create().resource(p).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
client.create().resource(p).conditional().where(new StringClientParam("name").matches().value("foo")).execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
}
@Test
public void testUpdateConditional() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Patient p = new Patient();
p.addName().addFamily("FOOFAMILY");
client.update().resource(p).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.update().resource(p).conditional().where(new StringClientParam("name").matches().value("foo")).and(new StringClientParam("address").matches().value("AAA|BBB")).execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo&address=AAA%5C%7CBBB", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditional().where(new StringClientParam("name").matches().value("foo")).and(new StringClientParam("address").matches().value("AAA|BBB")).execute();
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("http://example.com/fhir/Patient?name=foo&address=AAA%5C%7CBBB", capt.getAllValues().get(idx).getURI().toString());
idx++;
}
private String extractBody(ArgumentCaptor<HttpUriRequest> capt, int count) throws IOException {
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(count)).getEntity().getContent(), "UTF-8");
return body;
}
}

View File

@ -0,0 +1,307 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.instance.model.Parameters;
import org.hl7.fhir.instance.model.Patient;
import org.hl7.fhir.instance.model.StringType;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.server.Constants;
public class OperationClientTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationClientTest.class);
private FhirContext ourCtx;
private HttpClient ourHttpClient;
private HttpResponse ourHttpResponse;
@Before
public void before() {
ourCtx = FhirContext.forDstu2Hl7Org();
ourHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
ourCtx.getRestfulClientFactory().setHttpClient(ourHttpClient);
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
ourHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
@Test
public void testOpInstance() throws Exception {
Parameters outParams = new Parameters();
outParams.addParameter().setName("FOO");
final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8"));
}
});
IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo");
int idx = 0;
Parameters response = client.opInstance(new IdDt("222"), new StringType("PARAM1str"), new Patient().setActive(true));
assertEquals("FOO", response.getParameter().get(0).getName());
HttpPost value = (HttpPost) capt.getAllValues().get(idx);
String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/Patient/222/$OP_INSTANCE", value.getURI().toASCIIString());
assertEquals(2, request.getParameter().size());
assertEquals("PARAM1", request.getParameter().get(0).getName());
assertEquals("PARAM1str", ((StringType) request.getParameter().get(0).getValue()).getValue());
assertEquals("PARAM2", request.getParameter().get(1).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive());
idx++;
}
@Test
public void testOpServer() throws Exception {
Parameters outParams = new Parameters();
outParams.addParameter().setName("FOO");
final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8"));
}
});
IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo");
int idx = 0;
Parameters response = client.opServer(new StringType("PARAM1str"), new Patient().setActive(true));
assertEquals("FOO", response.getParameter().get(0).getName());
HttpPost value = (HttpPost) capt.getAllValues().get(idx);
String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/$OP_SERVER", value.getURI().toASCIIString());
assertEquals(2, request.getParameter().size());
assertEquals("PARAM1", request.getParameter().get(0).getName());
assertEquals("PARAM1str", ((StringType) request.getParameter().get(0).getValue()).getValue());
assertEquals("PARAM2", request.getParameter().get(1).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive());
idx++;
response = client.opServer(null, new Patient().setActive(true));
assertEquals("FOO", response.getParameter().get(0).getName());
value = (HttpPost) capt.getAllValues().get(idx);
requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals(1, request.getParameter().size());
assertEquals("PARAM2", request.getParameter().get(0).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(0).getResource()).getActive());
idx++;
response = client.opServer(null, null);
assertEquals("FOO", response.getParameter().get(0).getName());
value = (HttpPost) capt.getAllValues().get(idx);
requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals(0, request.getParameter().size());
idx++;
}
@Test
public void testOpWithListParam() throws Exception {
Parameters outParams = new Parameters();
outParams.addParameter().setName("FOO");
final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8"));
}
});
IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo");
int idx = 0;
Parameters response = client.opServerListParam(new Patient().setActive(true), Arrays.asList(new StringType("PARAM3str1"), new StringType("PARAM3str2")));
assertEquals("FOO", response.getParameter().get(0).getName());
HttpPost value = (HttpPost) capt.getAllValues().get(idx);
String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString());
assertEquals(3, request.getParameter().size());
assertEquals("PARAM2", request.getParameter().get(0).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(0).getResource()).getActive());
assertEquals("PARAM3", request.getParameter().get(1).getName());
assertEquals("PARAM3str1", ((StringType) request.getParameter().get(1).getValue()).getValue());
assertEquals("PARAM3", request.getParameter().get(2).getName());
assertEquals("PARAM3str2", ((StringType) request.getParameter().get(2).getValue()).getValue());
idx++;
response = client.opServerListParam(null, Arrays.asList(new StringType("PARAM3str1"), new StringType("PARAM3str2")));
assertEquals("FOO", response.getParameter().get(0).getName());
value = (HttpPost) capt.getAllValues().get(idx);
requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString());
assertEquals(2, request.getParameter().size());
assertEquals("PARAM3", request.getParameter().get(0).getName());
assertEquals("PARAM3str1", ((StringType) request.getParameter().get(0).getValue()).getValue());
assertEquals("PARAM3", request.getParameter().get(1).getName());
assertEquals("PARAM3str2", ((StringType) request.getParameter().get(1).getValue()).getValue());
idx++;
response = client.opServerListParam(null, new ArrayList<StringType>());
assertEquals("FOO", response.getParameter().get(0).getName());
value = (HttpPost) capt.getAllValues().get(idx);
requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString());
assertEquals(0, request.getParameter().size());
idx++;
response = client.opServerListParam(null, null);
assertEquals("FOO", response.getParameter().get(0).getName());
value = (HttpPost) capt.getAllValues().get(idx);
requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString());
assertEquals(0, request.getParameter().size());
idx++;
}
@Test
public void testOpType() throws Exception {
Parameters outParams = new Parameters();
outParams.addParameter().setName("FOO");
final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8"));
}
});
IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo");
int idx = 0;
Parameters response = client.opType(new StringType("PARAM1str"), new Patient().setActive(true));
assertEquals("FOO", response.getParameter().get(0).getName());
HttpPost value = (HttpPost) capt.getAllValues().get(idx);
String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/Patient/$OP_TYPE", value.getURI().toASCIIString());
assertEquals(2, request.getParameter().size());
assertEquals("PARAM1", request.getParameter().get(0).getName());
assertEquals("PARAM1str", ((StringType) request.getParameter().get(0).getValue()).getValue());
assertEquals("PARAM2", request.getParameter().get(1).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive());
idx++;
}
public interface IOpClient extends IBasicClient {
//@formatter:off
@Operation(name="$OP_INSTANCE", type=Patient.class)
public Parameters opInstance(
@IdParam IdDt theId,
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
);
//@formatter:on
//@formatter:off
@Operation(name="$OP_SERVER")
public Parameters opServer(
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
);
//@formatter:on
//@formatter:off
@Operation(name="$OP_SERVER_LIST_PARAM")
public Parameters opServerListParam(
@OperationParam(name="PARAM2") Patient theParam2,
@OperationParam(name="PARAM3") List<StringType> theParam3
);
//@formatter:on
//@formatter:off
@Operation(name="$OP_TYPE", type=Patient.class)
public Parameters opType(
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
);
//@formatter:on
}
}

View File

@ -1,127 +1 @@
/target/
# Created by https://www.gitignore.io
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
/build/

View File

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>hapi-fhir-testpage-overlay</name>
<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
<comment></comment>
<projects>
<project>hapi-fhir-jpaserver-base</project>
<project>hapi-fhir-jpaserver-test</project>
</projects>
<buildSpec>
<buildCommand>
@ -13,12 +11,12 @@
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
@ -34,11 +32,11 @@
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

View File

@ -78,12 +78,13 @@ SPAN.headerValue {
}
SPAN.includeCheckContainer {
margin-top: 6px;
margin-bottom: 6px;
margin-top: 2px;
margin-bottom: 2px;
margin-right: 0px;
margin-left: 15px;
margin-left: 2px;
white-space: nowrap;
line-height: 35px;
display: inline-block;
}
SPAN.includeCheckCheck {

View File

@ -106,7 +106,6 @@ public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
retVal.add(("/dt/" + version + "/attachment.xml"));
retVal.add(("/dt/" + version + "/contactpoint.xml"));
retVal.add(("/dt/" + version + "/elementdefinition.xml"));
retVal.add(("/dt/" + version + "/reference.xml"));
retVal.add(("/dt/" + version + "/timing.xml"));
retVal.add(("/dt/" + version + "/signature.xml"));
}

View File

@ -130,6 +130,12 @@
JPA server failed to index resources containing ContactPointDt elements with
populated values (e.g. Patient.telecom). Thanks to Mohammad Jafari for reporting!
</action>
<action type="add">
Add a new configuration method on the parsers,
<![CDATA[<code>setStripVersionsFromReferences(boolean)</code>]]> which
configures the parser to preserve versions in resource reference links when
encoding. By default, these are removed.
</action>
</release>
<release version="0.9" date="2015-Mar-14">
<action type="add">