Many bugfixes
This commit is contained in:
parent
79bdd94f72
commit
cb19b17e59
|
@ -33,6 +33,8 @@
|
|||
|
||||
* Support "Binary" resource, which is a special resource type
|
||||
|
||||
* Submit "_pretty" as possible parameter to HL7
|
||||
|
||||
---------
|
||||
Issues:
|
||||
* Need to be able to bind Identifier.system to a set of allowable values in a profile. Graeme
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Set;
|
|||
import ca.uhn.fhir.model.api.ICodeEnum;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
||||
|
@ -35,7 +34,8 @@ public abstract class BaseRuntimeChildDatatypeDefinition extends BaseRuntimeDecl
|
|||
|
||||
@Override
|
||||
public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IElement> theDatatype) {
|
||||
if (myDatatype.equals(theDatatype)) {
|
||||
Class<? extends IElement> datatype = theDatatype;
|
||||
if (myDatatype.equals(datatype)) {
|
||||
return myElementDefinition;
|
||||
}
|
||||
return null;
|
||||
|
@ -74,4 +74,11 @@ public abstract class BaseRuntimeChildDatatypeDefinition extends BaseRuntimeDecl
|
|||
}
|
||||
myCodeType = theType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + getElementName() + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,5 @@ public class RuntimeChildCompositeDatatypeDefinition extends BaseRuntimeChildDat
|
|||
super(theField, theElementName, theChildAnnotation,theDescriptionAnnotation, theDatatype);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -83,4 +83,9 @@ public class RuntimeChildResourceDefinition extends BaseRuntimeDeclaredChildDefi
|
|||
|
||||
myValidChildNames = Collections.unmodifiableSet(myValidChildNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + getElementName() + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class BoundCodeableConceptDt<T extends Enum<?>> extends CodeableConceptDt
|
|||
return;
|
||||
}
|
||||
for (T next : theValues) {
|
||||
getCoding().add(new BoundCodingDt<T>(myBinder, next));
|
||||
getCoding().add(new CodingDt(myBinder.toSystemString(next), myBinder.toCodeString(next)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,16 +5,16 @@ import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
|||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
|
||||
@DatatypeDef(name = "Coding")
|
||||
public class BoundCodingDt<T extends Enum<?>> extends CodingDt {
|
||||
@DatatypeDef(name = "Coding", isSpecialization=true)
|
||||
public class BoundCodingDt__<T extends Enum<?>> extends CodingDt {
|
||||
|
||||
private IValueSetEnumBinder<T> myBinder;
|
||||
|
||||
public BoundCodingDt(IValueSetEnumBinder<T> theBinder) {
|
||||
public BoundCodingDt__(IValueSetEnumBinder<T> theBinder) {
|
||||
myBinder = theBinder;
|
||||
}
|
||||
|
||||
public BoundCodingDt(IValueSetEnumBinder<T> theBinder, T theValue) {
|
||||
public BoundCodingDt__(IValueSetEnumBinder<T> theBinder, T theValue) {
|
||||
myBinder = theBinder;
|
||||
setValueAsEnum(theValue);
|
||||
}
|
|
@ -8,10 +8,8 @@ import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
|||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
/**
|
||||
* Represents the FHIR ID type. This is the actual resource ID, meaning the ID that
|
||||
* will be used in RESTful URLs, Resource References, etc. to represent a specific
|
||||
* instance of a resource.
|
||||
*
|
||||
* Represents the FHIR ID type. This is the actual resource ID, meaning the ID that will be used in RESTful URLs, Resource References, etc. to represent a specific instance of a resource.
|
||||
*
|
||||
* <p>
|
||||
* <b>Description</b>: A whole number in the range 0 to 2^64-1 (optionally represented in hex), a uuid, an oid, or any other combination of lowercase letters, numerals, "-" and ".", with a length
|
||||
* limit of 36 characters.
|
||||
|
@ -32,6 +30,17 @@ public class IdDt extends BasePrimitive<String> {
|
|||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ID, using a BigDecimal input. Uses {@link BigDecimal#toPlainString()} to generate the string representation.
|
||||
*/
|
||||
public IdDt(BigDecimal thePid) {
|
||||
if (thePid != null) {
|
||||
setValue(thePid.toPlainString());
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ID using a long
|
||||
*/
|
||||
|
@ -56,14 +65,24 @@ public class IdDt extends BasePrimitive<String> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a new ID, using a BigDecimal input. Uses {@link BigDecimal#toPlainString()} to generate the string representation.
|
||||
* Returns the value of this ID as a big decimal, or <code>null</code> if the value is null
|
||||
*
|
||||
* @throws NumberFormatException
|
||||
* If the value is not a valid BigDecimal
|
||||
*/
|
||||
public IdDt(BigDecimal thePid) {
|
||||
if (thePid != null) {
|
||||
setValue(thePid.toPlainString());
|
||||
} else {
|
||||
setValue(null);
|
||||
public BigDecimal asBigDecimal() {
|
||||
if (getValue() == null) {
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(getValueAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
|
||||
*/
|
||||
@Override
|
||||
public IdDt getId() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,6 +95,14 @@ public class IdDt extends BasePrimitive<String> {
|
|||
return myValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the value from the given IdDt to <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
|
||||
*/
|
||||
@Override
|
||||
public void setId(IdDt theId) {
|
||||
setValue(theId.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value
|
||||
*
|
||||
|
@ -114,16 +141,4 @@ public class IdDt extends BasePrimitive<String> {
|
|||
return myValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this ID as a big decimal, or <code>null</code> if the value is null
|
||||
*
|
||||
* @throws NumberFormatException If the value is not a valid BigDecimal
|
||||
*/
|
||||
public BigDecimal asBigDecimal() {
|
||||
if (getValue() == null){
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(getValueAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -101,5 +101,13 @@ public class StringDt extends BasePrimitive<String> implements IQueryParameterTy
|
|||
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() {
|
||||
return super.isEmpty() && StringUtils.isBlank(getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
writeTagWithTextNode(eventWriter, "id", nextEntry.getEntryId());
|
||||
|
||||
eventWriter.writeStartArray("link");
|
||||
writeAtomLink(eventWriter, "self", theBundle.getLinkSelf());
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
eventWriter.writeEnd();
|
||||
|
||||
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
|
||||
|
|
|
@ -100,7 +100,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase());
|
||||
|
||||
if (theBundle.getTotalResults().getValue() != null) {
|
||||
eventWriter.writeStartElement("os", "totalResults",OPENSEARCH_NS);
|
||||
eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
|
||||
eventWriter.writeNamespace("os", OPENSEARCH_NS);
|
||||
eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString());
|
||||
eventWriter.writeEndElement();
|
||||
|
@ -119,6 +119,13 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
eventWriter.writeStartElement("entry");
|
||||
|
||||
writeTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
|
||||
writeTagWithTextNode(eventWriter, "id", nextEntry.getEntryId());
|
||||
|
||||
if (!nextEntry.getLinkSelf().isEmpty()) {
|
||||
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
|
||||
}
|
||||
|
||||
eventWriter.writeStartElement("content");
|
||||
eventWriter.writeAttribute("type", "text/xml");
|
||||
|
||||
|
@ -138,10 +145,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
@Override
|
||||
public String encodeResourceToString(IResource theResource) throws DataFormatException {
|
||||
if (theResource==null) {
|
||||
if (theResource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
|
||||
Writer stringWriter = new StringWriter();
|
||||
encodeResourceToWriter(theResource, stringWriter);
|
||||
return stringWriter.toString();
|
||||
|
@ -200,8 +207,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
return parseResource(theResourceType, streamReader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
|
@ -290,7 +295,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(XMLStreamWriter theEventWriter, IElement nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl) throws XMLStreamException, DataFormatException {
|
||||
private void encodeChildElementToStreamWriter(XMLStreamWriter theEventWriter, IElement nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
if (nextValue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -355,7 +361,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(IElement theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children) throws XMLStreamException, DataFormatException {
|
||||
private void encodeCompositeElementChildrenToStreamWriter(IElement theElement, XMLStreamWriter theEventWriter, List<? extends BaseRuntimeChildDefinition> children) throws XMLStreamException,
|
||||
DataFormatException {
|
||||
for (BaseRuntimeChildDefinition nextChild : children) {
|
||||
List<? extends IElement> values = nextChild.getAccessor().getValues(theElement);
|
||||
if (values == null || values.isEmpty()) {
|
||||
|
@ -392,7 +399,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(IElement theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef) throws XMLStreamException, DataFormatException {
|
||||
private void encodeCompositeElementToStreamWriter(IElement theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef) throws XMLStreamException,
|
||||
DataFormatException {
|
||||
encodeExtensionsIfPresent(theEventWriter, theElement);
|
||||
encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getExtensions());
|
||||
encodeCompositeElementChildrenToStreamWriter(theElement, theEventWriter, resDef.getChildren());
|
||||
|
@ -419,22 +427,21 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter theEventWriter, boolean theIncludeResourceId) throws XMLStreamException, DataFormatException {
|
||||
super.containResourcesForEncoding(theResource);
|
||||
|
||||
|
||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||
if (resDef == null) {
|
||||
throw new ConfigurationException("Unknown resource type: " + theResource.getClass());
|
||||
}
|
||||
|
||||
|
||||
theEventWriter.writeStartElement(resDef.getName());
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
if (theIncludeResourceId && StringUtils.isNotBlank(theResource.getId().getValue())) {
|
||||
theEventWriter.writeAttribute("id", theResource.getId().getValue());
|
||||
}
|
||||
|
||||
|
||||
encodeCompositeElementToStreamWriter(theResource, theEventWriter, resDef);
|
||||
|
||||
theEventWriter.writeEndElement();
|
||||
|
@ -449,7 +456,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
IElement nextValue = next.getValue();
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(nextValue.getClass());
|
||||
if (childName==null) {
|
||||
if (childName == null) {
|
||||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + nextValue.getClass().getCanonicalName());
|
||||
}
|
||||
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(nextValue.getClass());
|
||||
|
@ -579,7 +586,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void writeTagWithTextNode(XMLStreamWriter theEventWriter, String theElementName, StringDt theStringDt) throws XMLStreamException {
|
||||
theEventWriter.writeStartElement(theElementName);
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
|
|
|
@ -10,11 +10,23 @@ import java.lang.annotation.Target;
|
|||
* be populated with the "_include" values for a search param.
|
||||
* <p>
|
||||
* Only one parameter may be annotated with this annotation, and that
|
||||
* parameter should be of type Collection, List, or Set.
|
||||
* parameter should be one of the following:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li><code>Collection<PathSpecification></code></li>
|
||||
* <li><code>List<PathSpecification></code></li>
|
||||
* <li><code>Set<PathSpecification></code></li>
|
||||
* </ul>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.PARAMETER})
|
||||
public @interface Include {
|
||||
|
||||
/**
|
||||
* Optional parameter, if provided the server will only allow the values
|
||||
* within the given set. If an _include parameter is passed to the server
|
||||
* which does not match any allowed values the server will return an error.
|
||||
*/
|
||||
String[] allow() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -106,6 +106,9 @@ public class SearchMethodBinding extends BaseMethodBinding {
|
|||
IParameter param = myParameters.get(i);
|
||||
String[] value = parameterValues.get(param.getName());
|
||||
if (value == null || value.length == 0) {
|
||||
if (param.handlesMissing()) {
|
||||
params[i] = param.parse(new ArrayList<List<String>>(0));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,20 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
|
||||
public interface IParameter {
|
||||
|
||||
public abstract List<List<String>> encode(Object theObject) throws InternalErrorException;
|
||||
List<List<String>> encode(Object theObject) throws InternalErrorException;
|
||||
|
||||
public abstract String getName();
|
||||
String getName();
|
||||
|
||||
public abstract Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException;
|
||||
Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
public abstract boolean isRequired();
|
||||
boolean isRequired();
|
||||
|
||||
/**
|
||||
* Parameter should return true if {@link #parse(List)} should be called even
|
||||
* if the query string contained no values for the given parameter
|
||||
*/
|
||||
boolean handlesMissing();
|
||||
|
||||
public abstract SearchParamTypeEnum getParamType();
|
||||
SearchParamTypeEnum getParamType();
|
||||
|
||||
}
|
|
@ -3,19 +3,29 @@ package ca.uhn.fhir.rest.param;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.rest.annotation.Include;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class IncludeParameter implements IParameter {
|
||||
|
||||
private Class<? extends Collection<PathSpecification>> myInstantiableCollectionType;
|
||||
private HashSet<String> myAllow;
|
||||
|
||||
public IncludeParameter(Class<? extends Collection<PathSpecification>> theInstantiableCollectionType) {
|
||||
public IncludeParameter(Include theAnnotation, Class<? extends Collection<PathSpecification>> theInstantiableCollectionType) {
|
||||
myInstantiableCollectionType = theInstantiableCollectionType;
|
||||
if (theAnnotation.allow().length > 0) {
|
||||
myAllow = new HashSet<String>();
|
||||
for (String next : theAnnotation.allow()) {
|
||||
myAllow.add(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -53,7 +63,13 @@ public class IncludeParameter implements IParameter {
|
|||
throw new InvalidRequestException("'OR' query parameters (values containing ',') are not supported in _include parameters");
|
||||
}
|
||||
|
||||
retVal.add(new PathSpecification(nextParamList.get(0)));
|
||||
String value = nextParamList.get(0);
|
||||
if (myAllow != null) {
|
||||
if (!myAllow.contains(value)) {
|
||||
throw new InvalidRequestException("Invalid _include parameter value: '" + value + "'. Valid values are: " + new TreeSet<String>(myAllow));
|
||||
}
|
||||
}
|
||||
retVal.add(new PathSpecification(value));
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
@ -69,4 +85,9 @@ public class IncludeParameter implements IParameter {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesMissing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,6 +100,8 @@ public class SearchParameter implements IParameter {
|
|||
throw new ConfigurationException("Unknown search parameter type: " + type);
|
||||
}
|
||||
|
||||
// NB: Once this is enabled, we should return true from handlesMissing if
|
||||
// it's a collection type
|
||||
// if (theInnerCollectionType != null) {
|
||||
// this.parser = new CollectionBinder(this.parser, theInnerCollectionType);
|
||||
// }
|
||||
|
@ -115,4 +117,9 @@ public class SearchParameter implements IParameter {
|
|||
return myParamType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesMissing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ public class Constants {
|
|||
public static final Set<String> FORMAT_VAL_XML;
|
||||
public static final Set<String> FORMAT_VAL_JSON;
|
||||
public static final Map<String, EncodingUtil> FORMAT_VAL_TO_ENCODING;
|
||||
public static final String CT_XML = "application/xml";
|
||||
public static final String CT_JSON = "application/json";
|
||||
|
||||
static {
|
||||
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
||||
|
|
|
@ -2,16 +2,20 @@ package ca.uhn.fhir.rest.server;
|
|||
|
||||
public enum EncodingUtil {
|
||||
|
||||
XML(Constants.CT_FHIR_XML, Constants.CT_ATOM_XML),
|
||||
XML(Constants.CT_FHIR_XML, Constants.CT_ATOM_XML, Constants.CT_XML),
|
||||
|
||||
JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON);
|
||||
JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON, Constants.CT_JSON)
|
||||
|
||||
;
|
||||
|
||||
private String myResourceContentType;
|
||||
private String myBundleContentType;
|
||||
|
||||
EncodingUtil(String theResourceContentType, String theBundleContentType) {
|
||||
private String myBrowserFriendlyContentType;
|
||||
|
||||
EncodingUtil(String theResourceContentType, String theBundleContentType, String theBrowserFriendlyContentType) {
|
||||
myResourceContentType = theResourceContentType;
|
||||
myBundleContentType = theBundleContentType;
|
||||
myBrowserFriendlyContentType = theBrowserFriendlyContentType;
|
||||
}
|
||||
|
||||
public String getBundleContentType() {
|
||||
|
@ -22,4 +26,8 @@ public enum EncodingUtil {
|
|||
return myResourceContentType;
|
||||
}
|
||||
|
||||
public String getBrowserFriendlyBundleContentType() {
|
||||
return myBrowserFriendlyContentType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,11 +40,24 @@ import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
|
|||
|
||||
public abstract class RestfulServer extends HttpServlet {
|
||||
|
||||
private static final String PARAM_HISTORY = "_history";
|
||||
private static final String PARAM_PRETTY = "_pretty";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FhirContext myFhirContext;
|
||||
private boolean myUseBrowserFriendlyContentTypes;
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is false), the server will use browser friendly
|
||||
* content-types (instead of standard FHIR ones) when it detects that the request
|
||||
* is coming from a browser instead of a FHIR
|
||||
*/
|
||||
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
|
||||
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
|
||||
}
|
||||
|
||||
private Map<Class<? extends IResource>, IResourceProvider> myTypeToProvider = new HashMap<Class<? extends IResource>, IResourceProvider>();
|
||||
|
||||
|
@ -75,18 +88,17 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
}
|
||||
return EncodingUtil.XML;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
handleRequest(SearchMethodBinding.RequestType.DELETE, request, response);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
handleRequest(SearchMethodBinding.RequestType.GET, request, response);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doOptions(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
|
||||
handleRequest(SearchMethodBinding.RequestType.OPTIONS, theReq, theResp);
|
||||
|
@ -102,7 +114,6 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
handleRequest(SearchMethodBinding.RequestType.PUT, request, response);
|
||||
}
|
||||
|
||||
|
||||
private void findResourceMethods(IResourceProvider theProvider) throws Exception {
|
||||
|
||||
Class<? extends IResource> resourceType = theProvider.getResourceType();
|
||||
|
@ -131,12 +142,11 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
private IParser getNewParser(EncodingUtil theResponseEncoding) {
|
||||
private IParser getNewParser(EncodingUtil theResponseEncoding, boolean thePrettyPrint) {
|
||||
IParser parser;
|
||||
switch (theResponseEncoding) {
|
||||
case JSON:
|
||||
|
@ -147,7 +157,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
parser = myFhirContext.newXmlParser();
|
||||
break;
|
||||
}
|
||||
return parser;
|
||||
return parser.setPrettyPrint(thePrettyPrint);
|
||||
}
|
||||
|
||||
public Collection<ResourceBinding> getResourceBindings() {
|
||||
|
@ -160,8 +170,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
public abstract Collection<IResourceProvider> getResourceProviders();
|
||||
|
||||
/**
|
||||
* This method should be overridden to provide a security manager instance.
|
||||
* By default, returns null.
|
||||
* This method should be overridden to provide a security manager instance. By default, returns null.
|
||||
*/
|
||||
public ISecurityManager getSecurityManager() {
|
||||
return null;
|
||||
|
@ -181,40 +190,61 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
if (null != securityManager) {
|
||||
securityManager.authenticate(request);
|
||||
}
|
||||
|
||||
String uaHeader = request.getHeader("user-agent");
|
||||
boolean requestIsBrowser = false;
|
||||
if (uaHeader != null && uaHeader.contains("Mozilla")) {
|
||||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
|
||||
String resourceName = null;
|
||||
String requestFullPath = StringUtils.defaultString(request.getRequestURI());
|
||||
// String contextPath = StringUtils.defaultString(request.getContextPath());
|
||||
// String contextPath = StringUtils.defaultString(request.getContextPath());
|
||||
String servletPath = StringUtils.defaultString(request.getServletPath());
|
||||
StringBuffer requestUrl = request.getRequestURL();
|
||||
String servletContextPath = "";
|
||||
if (request.getServletContext() != null) {
|
||||
servletContextPath = StringUtils.defaultString(request.getServletContext().getContextPath());
|
||||
}
|
||||
|
||||
|
||||
ourLog.info("Request FullPath: {}", requestFullPath);
|
||||
ourLog.info("Servlet Path: {}", servletPath);
|
||||
ourLog.info("Request Url: {}", requestUrl);
|
||||
ourLog.info("Context Path: {}", servletContextPath);
|
||||
|
||||
servletPath = servletContextPath;
|
||||
|
||||
|
||||
IdDt id = null;
|
||||
IdDt versionId = null;
|
||||
String operation = null;
|
||||
|
||||
String operation = null;
|
||||
|
||||
String requestPath = requestFullPath.substring(servletPath.length());
|
||||
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
|
||||
requestPath = requestPath.substring(1);
|
||||
}
|
||||
|
||||
int contextIndex = requestUrl.indexOf(servletPath);
|
||||
int contextIndex;
|
||||
if (servletPath.length()==0) {
|
||||
contextIndex = requestUrl.indexOf(requestPath);
|
||||
}else {
|
||||
contextIndex = requestUrl.indexOf(servletPath);
|
||||
}
|
||||
|
||||
String fhirServerBase = requestUrl.substring(0, contextIndex + servletPath.length());
|
||||
String completeUrl = StringUtils.isNotBlank(request.getQueryString()) ? requestUrl + "?" + request.getQueryString() : requestUrl.toString();
|
||||
|
||||
|
||||
Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
|
||||
EncodingUtil responseEncoding = determineResponseEncoding(request, params);
|
||||
|
||||
String[] pretty = params.remove(PARAM_PRETTY);
|
||||
boolean prettyPrint = false;
|
||||
if (pretty != null && pretty.length > 0) {
|
||||
if ("true".equals(pretty[0])) {
|
||||
prettyPrint = true;
|
||||
}
|
||||
}
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(requestPath, "/");
|
||||
if (!tok.hasMoreTokens()) {
|
||||
throw new MethodNotFoundException("No resource name specified");
|
||||
|
@ -228,7 +258,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
} else {
|
||||
resourceBinding = resources.get(resourceName);
|
||||
}
|
||||
|
||||
|
||||
if (resourceBinding == null) {
|
||||
throw new MethodNotFoundException("Unknown resource type: " + resourceName);
|
||||
}
|
||||
|
@ -244,7 +274,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (nextString.startsWith("_history")) {
|
||||
if (nextString.startsWith(PARAM_HISTORY)) {
|
||||
if (tok.hasMoreTokens()) {
|
||||
versionId = new IdDt(tok.nextToken());
|
||||
} else {
|
||||
|
@ -271,7 +301,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
List<IResource> result = resourceMethod.invokeServer(resourceBinding.getResourceProvider(), id, versionId, params);
|
||||
switch (resourceMethod.getReturnType()) {
|
||||
case BUNDLE:
|
||||
streamResponseAsBundle(response, result, responseEncoding, fhirServerBase, completeUrl);
|
||||
streamResponseAsBundle(response, result, responseEncoding, fhirServerBase, completeUrl, prettyPrint, requestIsBrowser);
|
||||
break;
|
||||
case RESOURCE:
|
||||
if (result.size() == 0) {
|
||||
|
@ -279,7 +309,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
} else if (result.size() > 1) {
|
||||
throw new InternalErrorException("Method returned multiple resources");
|
||||
}
|
||||
streamResponseAsResource(response, result.get(0), resourceBinding, responseEncoding);
|
||||
streamResponseAsResource(response, result.get(0), responseEncoding, prettyPrint, requestIsBrowser);
|
||||
break;
|
||||
}
|
||||
// resourceMethod.get
|
||||
|
@ -334,7 +364,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
for (IResourceProvider provider : myTypeToProvider.values()) {
|
||||
findResourceMethods(provider);
|
||||
}
|
||||
|
||||
|
||||
findResourceMethods(getServerProfilesProvider());
|
||||
findResourceMethods(getServerConformanceProvider());
|
||||
|
||||
|
@ -344,16 +374,25 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
private void streamResponseAsBundle(HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theFhirServerBase, String theCompleteUrl) throws IOException {
|
||||
private void streamResponseAsBundle(HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase, String theCompleteUrl,
|
||||
boolean thePrettyPrint, boolean theRequestIsBrowser) throws IOException {
|
||||
assert theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBundleContentType());
|
||||
|
||||
if (theRequestIsBrowser && myUseBrowserFriendlyContentTypes) {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBundleContentType());
|
||||
}
|
||||
|
||||
theHttpResponse.setCharacterEncoding("UTF-8");
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.getAuthorName().setValue(getClass().getCanonicalName());
|
||||
bundle.getBundleId().setValue(UUID.randomUUID().toString());
|
||||
bundle.getPublished().setToCurrentTimeInLocalTimeZone();
|
||||
bundle.getLinkBase().setValue(theFhirServerBase);
|
||||
bundle.getLinkBase().setValue(theServerBase);
|
||||
bundle.getLinkSelf().setValue(theCompleteUrl);
|
||||
|
||||
for (IResource next : theResult) {
|
||||
|
@ -361,23 +400,55 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
bundle.getEntries().add(entry);
|
||||
|
||||
entry.setResource(next);
|
||||
|
||||
RuntimeResourceDefinition def = myFhirContext.getResourceDefinition(next);
|
||||
|
||||
if (next.getId() != null && StringUtils.isNotBlank(next.getId().getValue())) {
|
||||
entry.getEntryId().setValue(next.getId().getValue());
|
||||
entry.getTitle().setValue(def.getName() + " " + next.getId().getValue());
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theServerBase);
|
||||
b.append(def.getName());
|
||||
b.append('/');
|
||||
b.append(next.getId().getValue());
|
||||
boolean haveQ = false;
|
||||
if (thePrettyPrint) {
|
||||
b.append('?').append(PARAM_PRETTY).append("=true");
|
||||
haveQ = true;
|
||||
}
|
||||
if (theResponseEncoding == EncodingUtil.JSON) {
|
||||
if (!haveQ) {
|
||||
b.append('?');
|
||||
haveQ = true;
|
||||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
b.append(Constants.PARAM_FORMAT).append("=json");
|
||||
}
|
||||
entry.getLinkSelf().setValue(b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
bundle.getTotalResults().setValue(theResult.size());
|
||||
|
||||
PrintWriter writer = theHttpResponse.getWriter();
|
||||
getNewParser(theResponseEncoding).encodeBundleToWriter(bundle, writer);
|
||||
getNewParser(theResponseEncoding, thePrettyPrint).encodeBundleToWriter(bundle, writer);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private void streamResponseAsResource(HttpServletResponse theHttpResponse, IResource theResource, ResourceBinding theResourceBinding, EncodingUtil theResponseEncoding) throws IOException {
|
||||
private void streamResponseAsResource(HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser) throws IOException {
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
theHttpResponse.setContentType(theResponseEncoding.getResourceContentType());
|
||||
if (theRequestIsBrowser && myUseBrowserFriendlyContentTypes) {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBundleContentType());
|
||||
}
|
||||
theHttpResponse.setCharacterEncoding("UTF-8");
|
||||
|
||||
PrintWriter writer = theHttpResponse.getWriter();
|
||||
getNewParser(theResponseEncoding).encodeResourceToWriter(theResource, writer);
|
||||
getNewParser(theResponseEncoding, thePrettyPrint).encodeResourceToWriter(theResource, writer);
|
||||
writer.close();
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ch.qos.logback.core.joran.action.ParamAction;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.rest.annotation.Include;
|
||||
|
@ -89,7 +88,7 @@ public class Util {
|
|||
}
|
||||
Class<? extends Collection<PathSpecification>> instantiableCollectionType = (Class<? extends Collection<PathSpecification>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + method.getName() + "'");
|
||||
|
||||
param = new IncludeParameter(instantiableCollectionType);
|
||||
param = new IncludeParameter((Include) nextAnnotation, instantiableCollectionType);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ca.uhn.fhir.rest.server.provider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -22,13 +21,11 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ReadMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.util.DatatypeUtil;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ public class ElementUtil {
|
|||
if (!isEmpty((List<? extends IElement>) next)) {
|
||||
return false;
|
||||
}
|
||||
} else if (next instanceof String && (!((String)next).isEmpty())) {
|
||||
return false;
|
||||
} else if (next != null && !((IElement) next).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public class PrettyPrintWriterWrapper implements XMLStreamWriter {
|
|||
@Override
|
||||
public void writeStartElement(String thePrefix, String theLocalName, String theNamespaceURI) throws XMLStreamException {
|
||||
indentAndAdd();
|
||||
myTarget.writeStartElement(thePrefix, theNamespaceURI, theLocalName);
|
||||
myTarget.writeStartElement(thePrefix, theLocalName, theNamespaceURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -138,8 +138,11 @@ public Class<? extends IResource> getResourceType() {
|
|||
|
||||
//START SNIPPET: pathSpec
|
||||
@Search()
|
||||
public List<DiagnosticReport> getDiagnosticReport( @Required(name=DiagnosticReport.SP_IDENTIFIER) IdentifierDt theIdentifier,
|
||||
@Include Set<PathSpecification> theIncludes ) {
|
||||
public List<DiagnosticReport> getDiagnosticReport(
|
||||
@Required(name=DiagnosticReport.SP_IDENTIFIER)
|
||||
IdentifierDt theIdentifier,
|
||||
@Include(allow= {"DiagnosticReport.subject"})
|
||||
Set<PathSpecification> theIncludes ) {
|
||||
List<DiagnosticReport> retVal = new ArrayList<DiagnosticReport>();
|
||||
|
||||
// Assume this method exists and loads the report from the DB
|
||||
|
|
|
@ -300,7 +300,7 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Invoking a client of thie type involves the following syntax:
|
||||
Invoking a client of this type involves the following syntax:
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
|
@ -328,6 +328,11 @@
|
|||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
<code>http://fhir.example.com/DiagnosticReport?subject.identifier=7000135&_include=DiagnosticReport.subject</code>
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -27,6 +27,8 @@ import ca.uhn.fhir.model.dstu.resource.Observation;
|
|||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.resource.Specimen;
|
||||
import ca.uhn.fhir.model.dstu.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.AdministrativeGenderCodesEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
|
||||
|
@ -43,6 +45,33 @@ public class XmlParserTest {
|
|||
assertEquals("Patient resource with id 3216379", bundle.getEntries().get(0).getTitle().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeBoundCode() throws IOException {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||
|
||||
patient.getGender().setValueAsEnum(AdministrativeGenderCodesEnum.M);
|
||||
|
||||
String val = new FhirContext().newXmlParser().encodeResourceToString(patient);
|
||||
ourLog.info(val);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeBundleResultCount() throws IOException {
|
||||
|
||||
Bundle b = new Bundle();
|
||||
b.getTotalResults().setValue(123);
|
||||
|
||||
String val = new FhirContext().newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(val);
|
||||
|
||||
assertThat(val, StringContains.containsString("<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">123</os:totalResults>"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseContainedResources() throws IOException {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -23,13 +23,15 @@ 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.hamcrest.core.IsNot;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.theories.Theories;
|
||||
|
||||
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.PathSpecification;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
|
@ -104,12 +106,60 @@ public class ResfulServerMethodTest {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
Patient patient = (Patient) bundle.getEntries().get(0).getResource();
|
||||
BundleEntry entry0 = bundle.getEntries().get(0);
|
||||
Patient patient = (Patient) entry0.getResource();
|
||||
assertEquals("include1", patient.getCommunication().get(0).getText().getValue());
|
||||
assertEquals("include2", patient.getAddress().get(0).getLine().get(0).getValue());
|
||||
assertEquals("include3", patient.getAddress().get(1).getLine().get(0).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithIncludesNone() throws Exception {
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
// Make sure there is no crash
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithIncludesBad() throws Exception {
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include4");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntryLinkSelf() throws Exception {
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
BundleEntry entry0 = bundle.getEntries().get(0);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkSelf().getValue());
|
||||
assertEquals("1", entry0.getEntryId().getValue());
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3&_format=json");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
bundle = ourCtx.newJsonParser().parseBundle(responseContent);
|
||||
entry0 = bundle.getEntries().get(0);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/1?_format=json", entry0.getLinkSelf().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchAllProfiles() throws Exception {
|
||||
|
||||
|
@ -216,18 +266,18 @@ public class ResfulServerMethodTest {
|
|||
assertEquals("urn:bbb|bbb", patient.getIdentifier().get(2).getValueAsQueryToken());
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testSearchByComplex() throws Exception {
|
||||
//
|
||||
// HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?Patient.identifier=urn:oid:2.16.840.1.113883.3.239.18.148%7C7000135&name=urn:oid:1.3.6.1.4.1.12201.102.5%7C522&date=");
|
||||
// HttpResponse status = ourClient.execute(httpGet);
|
||||
//
|
||||
// String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
// ourLog.info("Response was:\n{}", responseContent);
|
||||
//
|
||||
// assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
// }
|
||||
|
||||
// @Test
|
||||
// public void testSearchByComplex() throws Exception {
|
||||
//
|
||||
// HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?Patient.identifier=urn:oid:2.16.840.1.113883.3.239.18.148%7C7000135&name=urn:oid:1.3.6.1.4.1.12201.102.5%7C522&date=");
|
||||
// HttpResponse status = ourClient.execute(httpGet);
|
||||
//
|
||||
// String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
// ourLog.info("Response was:\n{}", responseContent);
|
||||
//
|
||||
// assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testSearchByDob() throws Exception {
|
||||
|
||||
|
@ -404,6 +454,31 @@ public class ResfulServerMethodTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrettyPrint() throws Exception {
|
||||
|
||||
// HttpPost httpPost = new HttpPost("http://localhost:" + ourPort +
|
||||
// "/Patient/1");
|
||||
// httpPost.setEntity(new StringEntity("test",
|
||||
// ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertThat(responseContent, StringContains.containsString("<identifier><use"));
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=false");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertThat(responseContent, StringContains.containsString("<identifier><use"));
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=true");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertThat(responseContent, IsNot.not(StringContains.containsString("<identifier><use")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetById() throws Exception {
|
||||
|
||||
|
@ -510,6 +585,7 @@ public class ResfulServerMethodTest {
|
|||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
patient.getId().setValue("1");
|
||||
idToPatient.put("1", patient);
|
||||
}
|
||||
{
|
||||
|
@ -522,13 +598,15 @@ public class ResfulServerMethodTest {
|
|||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientTwo");
|
||||
patient.getGender().setText("F");
|
||||
patient.getId().setValue("2");
|
||||
idToPatient.put("2", patient);
|
||||
}
|
||||
return idToPatient;
|
||||
}
|
||||
|
||||
@Search()
|
||||
public Patient getPatientWithIncludes(@Required(name = "withIncludes") StringDt theString, @Include List<PathSpecification> theIncludes) {
|
||||
public Patient getPatientWithIncludes(@Required(name = "withIncludes") StringDt theString,
|
||||
@Include(allow= {"include1","include2", "include3"}) List<PathSpecification> theIncludes) {
|
||||
Patient next = getIdToPatient().get("1");
|
||||
|
||||
next.addCommunication().setText(theString.getValue());
|
||||
|
@ -553,14 +631,11 @@ public class ResfulServerMethodTest {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public List<Patient> findDiagnosticReportsByPatient(
|
||||
@Required(name="Patient.identifier") IdentifierDt thePatientId,
|
||||
@Required(name=DiagnosticReport.SP_NAME) CodingListParam theNames,
|
||||
@Optional(name=DiagnosticReport.SP_DATE) DateRangeParam theDateRange
|
||||
) throws Exception {
|
||||
public List<Patient> findDiagnosticReportsByPatient(@Required(name = "Patient.identifier") IdentifierDt thePatientId, @Required(name = DiagnosticReport.SP_NAME) CodingListParam theNames,
|
||||
@Optional(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange) throws Exception {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@Search()
|
||||
public Patient getPatientWithDOB(@Required(name = "dob") QualifiedDateParam theDob) {
|
||||
Patient next = getIdToPatient().get("1");
|
||||
|
|
Loading…
Reference in New Issue