Adding history
This commit is contained in:
parent
acb5b02672
commit
84096da74d
|
@ -303,7 +303,7 @@
|
||||||
<replace dir="target/site" summary="true">
|
<replace dir="target/site" summary="true">
|
||||||
<include name="**/*.html"></include>
|
<include name="**/*.html"></include>
|
||||||
<replacefilter token="#build#" value="${label}" />
|
<replacefilter token="#build#" value="${label}" />
|
||||||
<replacefilter token="#version#" value="${version}" />
|
<replacefilter token="#version#" value="${project.version}" />
|
||||||
<replacetoken><![CDATA[</body>]]></replacetoken>
|
<replacetoken><![CDATA[</body>]]></replacetoken>
|
||||||
<replacevalue><![CDATA[
|
<replacevalue><![CDATA[
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -8,17 +8,21 @@ public interface IQueryParameterAnd {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @see See FHIR specification
|
* <p>
|
||||||
|
* See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException;
|
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @see See FHIR specification
|
* <p>
|
||||||
|
* See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public List<List<String>> getValuesAsQueryTokens();
|
public List<List<String>> getValuesAsQueryTokens();
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,11 @@ public interface IQueryParameterOr {
|
||||||
/**
|
/**
|
||||||
* Sets the value of this type using the <b>token</b> format. This
|
* Sets the value of this type using the <b>token</b> format. This
|
||||||
* format is used in HTTP queries as a parameter format.
|
* format is used in HTTP queries as a parameter format.
|
||||||
*
|
* <p>
|
||||||
* @see See FHIR specification
|
* See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void setValuesAsQueryTokens(List<String> theParameters);
|
public void setValuesAsQueryTokens(List<String> theParameters);
|
||||||
|
|
||||||
|
@ -18,9 +19,11 @@ public interface IQueryParameterOr {
|
||||||
* Returns the value of this type using the <b>token</b> format. This
|
* Returns the value of this type using the <b>token</b> format. This
|
||||||
* format is used in HTTP queries as a parameter format.
|
* format is used in HTTP queries as a parameter format.
|
||||||
*
|
*
|
||||||
* @see See FHIR specification
|
* <p>
|
||||||
|
* See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public List<String> getValuesAsQueryTokens();
|
public List<String> getValuesAsQueryTokens();
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,10 @@ public interface IQueryParameterType {
|
||||||
* Sets the value of this type using the <b>token</b> format. This
|
* Sets the value of this type using the <b>token</b> format. This
|
||||||
* format is used in HTTP queries as a parameter format.
|
* format is used in HTTP queries as a parameter format.
|
||||||
*
|
*
|
||||||
* @see See FHIR specification
|
* <p>See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void setValueAsQueryToken(String theParameter);
|
public void setValueAsQueryToken(String theParameter);
|
||||||
|
|
||||||
|
@ -16,9 +17,10 @@ public interface IQueryParameterType {
|
||||||
* Returns the value of this type using the <b>token</b> format. This
|
* Returns the value of this type using the <b>token</b> format. This
|
||||||
* format is used in HTTP queries as a parameter format.
|
* format is used in HTTP queries as a parameter format.
|
||||||
*
|
*
|
||||||
* @see See FHIR specification
|
* <p>See FHIR specification
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||||
* for information on the <b>token</b> format
|
* for information on the <b>token</b> format
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public String getValueAsQueryToken();
|
public String getValueAsQueryToken();
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
||||||
* </ul>
|
* </ul>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param The extension to add. Can not be null.
|
* @param theExtension The extension to add. Can not be null.
|
||||||
*/
|
*/
|
||||||
void addUndeclaredExtension(ExtensionDt theExtension);
|
void addUndeclaredExtension(ExtensionDt theExtension);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.TimeZone;
|
||||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
@DatatypeDef(name="instant")
|
@DatatypeDef(name="instant")
|
||||||
public class InstantDt extends BaseDateTimeDt {
|
public class InstantDt extends BaseDateTimeDt {
|
||||||
|
@ -46,6 +47,17 @@ public class InstantDt extends BaseDateTimeDt {
|
||||||
setTimeZone(TimeZone.getDefault());
|
setTimeZone(TimeZone.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new InstantDt from a string value
|
||||||
|
*
|
||||||
|
* @param theString The string representation of the string. Must be in
|
||||||
|
* a valid format according to the FHIR specification
|
||||||
|
* @throws DataFormatException
|
||||||
|
*/
|
||||||
|
public InstantDt(String theString) {
|
||||||
|
setValueAsString(theString);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
|
boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
|
||||||
switch (thePrecision) {
|
switch (thePrecision) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
@DatatypeDef(name="integer")
|
@DatatypeDef(name = "integer")
|
||||||
public class IntegerDt extends BasePrimitive<Integer> {
|
public class IntegerDt extends BasePrimitive<Integer> {
|
||||||
|
|
||||||
private Integer myValue;
|
private Integer myValue;
|
||||||
|
@ -24,7 +24,17 @@ public class IntegerDt extends BasePrimitive<Integer> {
|
||||||
public IntegerDt(@SimpleSetter.Parameter(name = "theInteger") int theInteger) {
|
public IntegerDt(@SimpleSetter.Parameter(name = "theInteger") int theInteger) {
|
||||||
setValue(theInteger);
|
setValue(theInteger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param theIntegerAsString A string representation of an integer
|
||||||
|
* @throws DataFormatException If the string is not a valid integer representation
|
||||||
|
*/
|
||||||
|
public IntegerDt(String theIntegerAsString) {
|
||||||
|
setValueAsString(theIntegerAsString);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getValue() {
|
public Integer getValue() {
|
||||||
return myValue;
|
return myValue;
|
||||||
|
@ -39,17 +49,21 @@ public class IntegerDt extends BasePrimitive<Integer> {
|
||||||
public void setValueAsString(String theValue) throws DataFormatException {
|
public void setValueAsString(String theValue) throws DataFormatException {
|
||||||
if (theValue == null) {
|
if (theValue == null) {
|
||||||
myValue = null;
|
myValue = null;
|
||||||
}else {
|
} else {
|
||||||
myValue = Integer.parseInt(theValue);
|
try {
|
||||||
|
myValue = Integer.parseInt(theValue);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new DataFormatException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValueAsString() {
|
public String getValueAsString() {
|
||||||
if (myValue==null) {
|
if (myValue == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Integer.toString(myValue);
|
return Integer.toString(myValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter annotation for the _count parameter, which indicates to the
|
||||||
|
* server the maximum number of desired results.
|
||||||
|
*
|
||||||
|
* @see History
|
||||||
|
*/
|
||||||
|
@Target(value=ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Count {
|
||||||
|
//nothing
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RESTful method annotation to be used for the FHIR
|
||||||
|
* <a href="http://hl7.org/implement/standards/fhir/http.html#history">history</a> method.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* History returns a feed containing all versions (or a selected range of versions) of
|
||||||
|
* a resource or a specific set of resources.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The history command supports three usage patterns, as described in the
|
||||||
|
* <a href="http://hl7.org/implement/standards/fhir/http.html#history">FHIR history</a> documentation:
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* A search for the history of all resources on a server. In this case, {@link #resourceType()}
|
||||||
|
* should be set to {@link AllResources} (as is the default) and the method should not have an ID parameter.
|
||||||
|
* <ul><li>
|
||||||
|
* To invoke this pattern: <code>GET [base]/_history{?[parameters]&_format=[mime-type]}</code>
|
||||||
|
* </li></ul>
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* A search for the history of all instances of a specific resource type on a server. In this case, {@link #resourceType()}
|
||||||
|
* should be set to the specific resource type (e.g. {@link Patient Patient.class} and the method should not have an ID parameter.
|
||||||
|
* <ul><li>
|
||||||
|
* To invoke this pattern: <code>GET [base]/[type]/_history{?[parameters]&_format=[mime-type]}</code>
|
||||||
|
* </li></ul>
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* A search for the history of a specific instances of a specific resource type on a server. In this case, {@link #resourceType()}
|
||||||
|
* should be set to the specific resource type (e.g. {@link Patient Patient.class} and the method should
|
||||||
|
* have one parameter of type {@link IdDt} annotated with the {@link IdParam} annotation.
|
||||||
|
* <ul><li>
|
||||||
|
* To invoke this pattern: <code>GET [base]/[type]/[id]/_history{?[parameters]&_format=[mime-type]}</code>
|
||||||
|
* </li></ul>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see Count
|
||||||
|
* @see Since
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value=ElementType.METHOD)
|
||||||
|
public @interface History {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The resource type that this method applies to. See the {@link History History annotation type documentation}
|
||||||
|
* for information on usage patterns.
|
||||||
|
*/
|
||||||
|
Class<? extends IResource> resourceType() default AllResources.class;
|
||||||
|
|
||||||
|
|
||||||
|
interface AllResources extends IResource {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,8 +21,10 @@ public @interface Search {
|
||||||
/**
|
/**
|
||||||
* If specified, this the name for the Named Query
|
* If specified, this the name for the Named Query
|
||||||
*
|
*
|
||||||
* @see See the FHIR specification section on
|
* <p>
|
||||||
|
* See the FHIR specification section on
|
||||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#advanced">named queries</a>
|
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#advanced">named queries</a>
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
String queryName() default "";
|
String queryName() default "";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter annotation for the _since parameter, which indicates to the
|
||||||
|
* server that only results dated since the given instant will be returned.
|
||||||
|
*
|
||||||
|
* @see History
|
||||||
|
*/
|
||||||
|
@Target(value=ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Since {
|
||||||
|
//nothing
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhir.rest.method;
|
package ca.uhn.fhir.rest.method;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PushbackReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -48,7 +49,8 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
||||||
|
|
||||||
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
|
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
|
||||||
if (!allowVoidReturnType()) {
|
if (!allowVoidReturnType()) {
|
||||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName() + " method but it does not return " + MethodOutcome.class);
|
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName()
|
||||||
|
+ " method but it does not return " + MethodOutcome.class);
|
||||||
} else if (theMethod.getReturnType() == void.class) {
|
} else if (theMethod.getReturnType() == void.class) {
|
||||||
myReturnVoid = true;
|
myReturnVoid = true;
|
||||||
}
|
}
|
||||||
|
@ -76,9 +78,27 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
||||||
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
||||||
EncodingUtil ct = EncodingUtil.forContentType(theResponseMimeType);
|
EncodingUtil ct = EncodingUtil.forContentType(theResponseMimeType);
|
||||||
if (ct != null) {
|
if (ct != null) {
|
||||||
IParser parser = ct.newParser(getContext());
|
PushbackReader reader = new PushbackReader(theResponseReader);
|
||||||
OperationOutcome outcome = parser.parseResource(OperationOutcome.class, theResponseReader);
|
|
||||||
retVal.setOperationOutcome(outcome);
|
try {
|
||||||
|
int firstByte = reader.read();
|
||||||
|
if (firstByte == -1) {
|
||||||
|
ourLog.debug("No content in response, not going to read");
|
||||||
|
reader = null;
|
||||||
|
} else {
|
||||||
|
reader.unread(firstByte);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
ourLog.debug("No content in response, not going to read", e);
|
||||||
|
reader = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader != null) {
|
||||||
|
IParser parser = ct.newParser(getContext());
|
||||||
|
OperationOutcome outcome = parser.parseResource(OperationOutcome.class, reader);
|
||||||
|
retVal.setOperationOutcome(outcome);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
||||||
}
|
}
|
||||||
|
@ -191,8 +211,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses may override to allow a void method return type, which is
|
* Subclasses may override to allow a void method return type, which is allowable for some methods (e.g. delete)
|
||||||
* allowable for some methods (e.g. delete)
|
|
||||||
*/
|
*/
|
||||||
protected boolean allowVoidReturnType() {
|
protected boolean allowVoidReturnType() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
package ca.uhn.fhir.rest.method;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||||
|
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.annotation.History;
|
||||||
|
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
|
public class HistoryMethodBinding extends BaseMethodBinding {
|
||||||
|
|
||||||
|
private final Integer myIdParamIndex;
|
||||||
|
private final RestfulOperationTypeEnum myResourceOperationType;
|
||||||
|
private final Class<? extends IResource> myType;
|
||||||
|
private final RestfulOperationSystemEnum mySystemOperationType;
|
||||||
|
private String myResourceName;
|
||||||
|
private Integer mySinceParamIndex;
|
||||||
|
private Integer myCountParamIndex;
|
||||||
|
|
||||||
|
public HistoryMethodBinding(Method theMethod, FhirContext theConetxt, IResourceProvider theProvider) {
|
||||||
|
super(theMethod, theConetxt);
|
||||||
|
|
||||||
|
myIdParamIndex = Util.findIdParameterIndex(theMethod);
|
||||||
|
mySinceParamIndex = Util.findSinceParameterIndex(theMethod);
|
||||||
|
myCountParamIndex = Util.findCountParameterIndex(theMethod);
|
||||||
|
|
||||||
|
History historyAnnotation = theMethod.getAnnotation(History.class);
|
||||||
|
Class<? extends IResource> type = historyAnnotation.resourceType();
|
||||||
|
if (type == History.AllResources.class) {
|
||||||
|
if (theProvider != null) {
|
||||||
|
type = theProvider.getResourceType();
|
||||||
|
if (myIdParamIndex != null) {
|
||||||
|
myResourceOperationType = RestfulOperationTypeEnum.HISTORY_INSTANCE;
|
||||||
|
} else {
|
||||||
|
myResourceOperationType = RestfulOperationTypeEnum.HISTORY_TYPE;
|
||||||
|
}
|
||||||
|
mySystemOperationType = null;
|
||||||
|
} else {
|
||||||
|
myResourceOperationType = null;
|
||||||
|
mySystemOperationType = RestfulOperationSystemEnum.HISTORY_SYSTEM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (myIdParamIndex != null) {
|
||||||
|
myResourceOperationType = RestfulOperationTypeEnum.HISTORY_INSTANCE;
|
||||||
|
} else {
|
||||||
|
myResourceOperationType = RestfulOperationTypeEnum.HISTORY_TYPE;
|
||||||
|
}
|
||||||
|
mySystemOperationType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != History.AllResources.class) {
|
||||||
|
myResourceName = theConetxt.getResourceDefinition(type).getName();
|
||||||
|
myType = type;
|
||||||
|
} else {
|
||||||
|
myResourceName = null;
|
||||||
|
myType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||||
|
return myResourceOperationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestfulOperationSystemEnum getSystemOperationType() {
|
||||||
|
return mySystemOperationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||||
|
Object[] args = new Object[getMethod().getParameterTypes().length];
|
||||||
|
if (myCountParamIndex != null) {
|
||||||
|
String[] countValues = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||||
|
if (countValues.length > 0 && StringUtils.isNotBlank(countValues[0])) {
|
||||||
|
try {
|
||||||
|
args[myCountParamIndex] = new IntegerDt(countValues[0]);
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
throw new InvalidRequestException("Invalid _count parameter value: " + countValues[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mySinceParamIndex != null) {
|
||||||
|
String[] sinceValues = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||||
|
if (sinceValues.length > 0 && StringUtils.isNotBlank(sinceValues[0])) {
|
||||||
|
try {
|
||||||
|
args[mySinceParamIndex] = new InstantDt(sinceValues[0]);
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
throw new InvalidRequestException("Invalid _since parameter value: " + sinceValues[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Request theRequest) {
|
||||||
|
if (!theRequest.getOperation().equals(Constants.PARAM_HISTORY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (theRequest.getResourceName() == null) {
|
||||||
|
return mySystemOperationType == RestfulOperationSystemEnum.HISTORY_SYSTEM;
|
||||||
|
}
|
||||||
|
if (!theRequest.getResourceName().equals(myResourceName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,11 +13,13 @@ import java.util.Map;
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.PathSpecification;
|
import ca.uhn.fhir.model.api.PathSpecification;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Count;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Since;
|
||||||
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
||||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||||
import ca.uhn.fhir.rest.param.IParameter;
|
import ca.uhn.fhir.rest.param.IParameter;
|
||||||
|
@ -30,6 +32,37 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
* Created by dsotnikov on 2/25/2014.
|
* Created by dsotnikov on 2/25/2014.
|
||||||
*/
|
*/
|
||||||
class Util {
|
class Util {
|
||||||
|
public static Integer findCountParameterIndex(Method theMethod) {
|
||||||
|
return findParamIndex(theMethod, Count.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer findIdParameterIndex(Method theMethod) {
|
||||||
|
return findParamIndex(theMethod, IdParam.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer findParamIndex(Method theMethod, Class<?> toFind) {
|
||||||
|
int paramIndex = 0;
|
||||||
|
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
|
||||||
|
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) {
|
||||||
|
Annotation nextAnnotation = annotations[annotationIndex];
|
||||||
|
Class<? extends Annotation> class1 = nextAnnotation.getClass();
|
||||||
|
if (toFind.isAssignableFrom(class1)) {
|
||||||
|
return paramIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer findSinceParameterIndex(Method theMethod) {
|
||||||
|
return findParamIndex(theMethod, Since.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer findVersionIdParameterIndex(Method theMethod) {
|
||||||
|
return findParamIndex(theMethod, VersionIdParam.class);
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<String, String> getQueryParams(String query) {
|
public static Map<String, String> getQueryParams(String query) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -58,10 +91,10 @@ class Util {
|
||||||
for (int i = 0; i < annotations.length; i++) {
|
for (int i = 0; i < annotations.length; i++) {
|
||||||
Annotation nextAnnotation = annotations[i];
|
Annotation nextAnnotation = annotations[i];
|
||||||
Class<?> parameterType = parameterTypes[paramIndex];
|
Class<?> parameterType = parameterTypes[paramIndex];
|
||||||
|
|
||||||
Class<? extends java.util.Collection<?>> outerCollectionType = null;
|
Class<? extends java.util.Collection<?>> outerCollectionType = null;
|
||||||
Class<? extends java.util.Collection<?>> innerCollectionType = null;
|
Class<? extends java.util.Collection<?>> innerCollectionType = null;
|
||||||
|
|
||||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
||||||
|
@ -88,14 +121,17 @@ class Util {
|
||||||
param = parameter;
|
param = parameter;
|
||||||
} else if (nextAnnotation instanceof IncludeParam) {
|
} else if (nextAnnotation instanceof IncludeParam) {
|
||||||
if (parameterType != PathSpecification.class || innerCollectionType == null || outerCollectionType != null) {
|
if (parameterType != PathSpecification.class || innerCollectionType == null || outerCollectionType != null) {
|
||||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"+PathSpecification.class.getSimpleName() + ">");
|
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"
|
||||||
|
+ PathSpecification.class.getSimpleName() + ">");
|
||||||
}
|
}
|
||||||
Class<? extends Collection<PathSpecification>> instantiableCollectionType = (Class<? extends Collection<PathSpecification>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + method.getName() + "'");
|
Class<? extends Collection<PathSpecification>> instantiableCollectionType = (Class<? extends Collection<PathSpecification>>) CollectionBinder.getInstantiableCollectionType(
|
||||||
|
innerCollectionType, "Method '" + method.getName() + "'");
|
||||||
|
|
||||||
param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType);
|
param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType);
|
||||||
} else if (nextAnnotation instanceof ResourceParam) {
|
} else if (nextAnnotation instanceof ResourceParam) {
|
||||||
if (!IResource.class.isAssignableFrom(parameterType)) {
|
if (!IResource.class.isAssignableFrom(parameterType)) {
|
||||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName() + " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName()
|
||||||
|
+ " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
||||||
}
|
}
|
||||||
param = new ResourceParameter((Class<? extends IResource>) parameterType);
|
param = new ResourceParameter((Class<? extends IResource>) parameterType);
|
||||||
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
||||||
|
@ -103,41 +139,20 @@ class Util {
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
haveHandledMethod= true;
|
haveHandledMethod = true;
|
||||||
parameters.add(param);
|
parameters.add(param);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!haveHandledMethod) {
|
if (!haveHandledMethod) {
|
||||||
throw new ConfigurationException("Parameter #" + paramIndex + " of method '" + method.getName() + "' on type '"+method.getDeclaringClass().getCanonicalName()+"' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
|
throw new ConfigurationException("Parameter #" + paramIndex + " of method '" + method.getName() + "' on type '" + method.getDeclaringClass().getCanonicalName()
|
||||||
|
+ "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer findIdParameterIndex(Method theMethod) {
|
|
||||||
return findParamIndex(theMethod, IdParam.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Integer findVersionIdParameterIndex(Method theMethod) {
|
|
||||||
return findParamIndex(theMethod, VersionIdParam.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Integer findParamIndex(Method theMethod, Class<?> toFind) {
|
|
||||||
int paramIndex = 0;
|
|
||||||
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
|
|
||||||
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) {
|
|
||||||
Annotation nextAnnotation = annotations[annotationIndex];
|
|
||||||
Class<? extends Annotation> class1 = nextAnnotation.getClass();
|
|
||||||
if (toFind.isAssignableFrom(class1)) {
|
|
||||||
return paramIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paramIndex++;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ public class Constants {
|
||||||
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
||||||
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
|
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
|
||||||
public static final int STATUS_HTTP_204_NO_CONTENT = 204;
|
public static final int STATUS_HTTP_204_NO_CONTENT = 204;
|
||||||
|
public static final String PARAM_COUNT = "_count";
|
||||||
|
public static final String PARAM_SINCE = "_since";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
||||||
|
|
|
@ -39,6 +39,7 @@ import ca.uhn.fhir.rest.param.CodingListParam;
|
||||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
|
||||||
|
@ -46,6 +47,8 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
public abstract class RestfulPatientResourceProviderMore implements IResourceProvider {
|
public abstract class RestfulPatientResourceProviderMore implements IResourceProvider {
|
||||||
|
|
||||||
private boolean detectedVersionConflict;
|
private boolean detectedVersionConflict;
|
||||||
|
private boolean conflictHappened;
|
||||||
|
private boolean couldntFindThisId;
|
||||||
//START SNIPPET: searchAll
|
//START SNIPPET: searchAll
|
||||||
@Search
|
@Search
|
||||||
public List<Organization> getAllOrganizations() {
|
public List<Organization> getAllOrganizations() {
|
||||||
|
@ -63,6 +66,22 @@ public Patient getResourceById(@IdParam IdDt theId) {
|
||||||
}
|
}
|
||||||
//END SNIPPET: read
|
//END SNIPPET: read
|
||||||
|
|
||||||
|
//START SNIPPET: delete
|
||||||
|
@Read()
|
||||||
|
public void deletePatient(@IdParam IdDt theId) {
|
||||||
|
// .. Delete the patient ..
|
||||||
|
if (couldntFindThisId) {
|
||||||
|
throw new ResourceNotFoundException("Unknown version");
|
||||||
|
}
|
||||||
|
if (conflictHappened) {
|
||||||
|
throw new ResourceVersionConflictException("Couldn't delete because [foo]");
|
||||||
|
}
|
||||||
|
// otherwise, delete was successful
|
||||||
|
return; // can also return MethodOutcome
|
||||||
|
}
|
||||||
|
//END SNIPPET: delete
|
||||||
|
|
||||||
|
|
||||||
//START SNIPPET: vread
|
//START SNIPPET: vread
|
||||||
@Read()
|
@Read()
|
||||||
public Patient getResourceById(@IdParam IdDt theId,
|
public Patient getResourceById(@IdParam IdDt theId,
|
||||||
|
|
|
@ -81,6 +81,10 @@
|
||||||
background-color: #F8F8F8 !important;
|
background-color: #F8F8F8 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table th, .table td {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
tt {
|
tt {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
|
|
@ -168,7 +168,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The
|
The
|
||||||
<a href="http://latest.fhir.me/http.html#read"><b>read</b></a>
|
<a href="http://hl7.org/implement/standards/fhir/http.html#read"><b>read</b></a>
|
||||||
operation retrieves a resource by ID. It is annotated with the
|
operation retrieves a resource by ID. It is annotated with the
|
||||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>
|
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>
|
||||||
annotation, and has a single parameter annotated with the
|
annotation, and has a single parameter annotated with the
|
||||||
|
@ -197,7 +197,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The
|
The
|
||||||
<a href="http://latest.fhir.me/http.html#vread"><b>vread</b></a>
|
<a href="http://hl7.org/implement/standards/fhir/http.html#vread"><b>vread</b></a>
|
||||||
operation retrieves a specific version of a resource with a given ID. It looks exactly
|
operation retrieves a specific version of a resource with a given ID. It looks exactly
|
||||||
like a "read" operation, but with a second
|
like a "read" operation, but with a second
|
||||||
parameter annotated with the
|
parameter annotated with the
|
||||||
|
@ -293,7 +293,40 @@
|
||||||
<a name="instance_delete"/>
|
<a name="instance_delete"/>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Not yet implemented
|
The
|
||||||
|
<a href="http://hl7.org/implement/standards/fhir/http.html#delete"><b>delete</b></a>
|
||||||
|
operation retrieves a specific version of a resource with a given ID. It takes a single
|
||||||
|
ID parameter annotated with an
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/annotation/IdParam.html">@IdParam</a>
|
||||||
|
annotation, which supplies the ID of the resource to delete.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="delete" />
|
||||||
|
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Delete methods are allowed to return the following types:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b>void</b>: This method may return <code>void</code>, in which case
|
||||||
|
the server will return an empty response and the client will ignore
|
||||||
|
any successful response from the server (failure responses will still throw
|
||||||
|
an exception)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b><a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a></b>:
|
||||||
|
This method may return <code>MethodOutcome</code>,
|
||||||
|
which is a wrapper for the FHIR OperationOutcome resource, which may optionally be returned
|
||||||
|
by the server according to the FHIR specification.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Example URL to invoke this method (HTTP DELETE):<br/>
|
||||||
|
<code>http://fhir.example.com/Patient/111</code>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -372,7 +405,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The
|
The
|
||||||
<a href="http://latest.fhir.me/http.html#search"><b>search</b></a> operation returns a bundle
|
<a href="http://hl7.org/implement/standards/fhir/http.html#search"><b>search</b></a> operation returns a bundle
|
||||||
with zero-to-many resources of a given type, matching a given set of parameters.
|
with zero-to-many resources of a given type, matching a given set of parameters.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class ClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ public class ClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||||
|
|
||||||
|
@ -181,6 +181,26 @@ public class ClientTest {
|
||||||
assertEquals("200", response.getVersionId().getValue());
|
assertEquals("200", response.getVersionId().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a FHIR content type, but no content and make sure we handle this without crashing
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithEmptyResponse() throws Exception {
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier("urn:foo", "123");
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||||
|
|
||||||
|
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||||
|
client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateWithVersion() throws Exception {
|
public void testUpdateWithVersion() throws Exception {
|
||||||
|
|
||||||
|
@ -190,7 +210,7 @@ public class ClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||||
|
|
||||||
|
@ -206,6 +226,7 @@ public class ClientTest {
|
||||||
assertEquals("200", response.getVersionId().getValue());
|
assertEquals("200", response.getVersionId().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected=ResourceVersionConflictException.class)
|
@Test(expected=ResourceVersionConflictException.class)
|
||||||
public void testUpdateWithResourceConflict() throws Exception {
|
public void testUpdateWithResourceConflict() throws Exception {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue