Indicate support for conditional create/update/delete in DSTU2 server conformance statement
This commit is contained in:
parent
2d05b48bdc
commit
8b65a9aedf
|
@ -85,10 +85,15 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
|||
public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseMethodBinding.class);
|
||||
/**
|
||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
||||
*/
|
||||
private static volatile IRequestReader ourRequestReader;
|
||||
private FhirContext myContext;
|
||||
private Method myMethod;
|
||||
private List<IParameter> myParameters;
|
||||
private Object myProvider;
|
||||
private boolean mySupportsConditional;
|
||||
|
||||
public BaseMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
assert theMethod != null;
|
||||
|
@ -98,6 +103,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
myContext = theContext;
|
||||
myProvider = theProvider;
|
||||
myParameters = MethodUtil.getResourceParameters(theContext, theMethod, theProvider, getResourceOperationType());
|
||||
|
||||
for (IParameter next : myParameters) {
|
||||
if (next instanceof ConditionalParamBinder) {
|
||||
mySupportsConditional = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingResponse(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode) {
|
||||
|
@ -223,7 +236,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
public abstract RestfulOperationTypeEnum getResourceOperationType();
|
||||
|
||||
/**
|
||||
* Returns the value of {@link #getResourceOperationType()} or {@link #getSystemOperationType()} or {@link #getOtherOperationType()}
|
||||
* Returns the value of {@link #getResourceOperationType()} or {@link #getSystemOperationType()} or
|
||||
* {@link #getOtherOperationType()}
|
||||
*/
|
||||
public String getResourceOrSystemOperationType() {
|
||||
Enum<?> retVal = getResourceOperationType();
|
||||
|
@ -264,11 +278,20 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this method have a parameter annotated with {@link ConditionalParamBinder}. Note that many operations don't
|
||||
* actually support this paramter, so this will only return true occasionally.
|
||||
*/
|
||||
public boolean isSupportsConditional() {
|
||||
return mySupportsConditional;
|
||||
}
|
||||
|
||||
protected byte[] loadRequestContents(RequestDetails theRequest) throws IOException {
|
||||
/*
|
||||
* This is weird, but this class is used both in clients and in servers, and we want to avoid needing to depend on servlet-api in clients since there is no point. So we dynamically load a class
|
||||
* that does the servlet processing in servers. Down the road it may make sense to just split the method binding classes into server and client versions, but this isn't actually a huge deal I
|
||||
* don't think.
|
||||
* This is weird, but this class is used both in clients and in servers, and we want to avoid needing to depend on
|
||||
* servlet-api in clients since there is no point. So we dynamically load a class that does the servlet processing
|
||||
* in servers. Down the road it may make sense to just split the method binding classes into server and client
|
||||
* versions, but this isn't actually a huge deal I don't think.
|
||||
*/
|
||||
IRequestReader reader = ourRequestReader;
|
||||
if (reader == null) {
|
||||
|
@ -385,16 +408,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (theProvider instanceof IResourceProvider) {
|
||||
returnTypeFromRp = ((IResourceProvider) theProvider).getResourceType();
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromRp)) {
|
||||
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned "
|
||||
+ toLogString(returnTypeFromRp) + " - Must return a resource type");
|
||||
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned " + toLogString(returnTypeFromRp) + " - Must return a resource type");
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> returnTypeFromMethod = theMethod.getReturnType();
|
||||
if (getTags != null) {
|
||||
if (!TagList.class.equals(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @"
|
||||
+ GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @" + GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
|
||||
}
|
||||
} else if (MethodOutcome.class.equals(returnTypeFromMethod)) {
|
||||
// returns a method outcome
|
||||
|
@ -407,15 +428,13 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
} else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
|
||||
returnTypeFromMethod = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromMethod) && !IResource.class.equals(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
|
||||
+ " returns a collection with generic type " + toLogString(returnTypeFromMethod)
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns a collection with generic type " + toLogString(returnTypeFromMethod)
|
||||
+ " - Must return a resource type or a collection (List, Set) with a resource type parameter (e.g. List<Patient> or List<IResource> )");
|
||||
}
|
||||
} else {
|
||||
if (!IResource.class.equals(returnTypeFromMethod) && !verifyIsValidResourceReturnType(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
|
||||
+ " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", " + IBundleProvider.class.getSimpleName()
|
||||
+ ", etc., see the documentation for more details)");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, "
|
||||
+ Bundle.class.getSimpleName() + ", " + IBundleProvider.class.getSimpleName() + ", etc., see the documentation for more details)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,13 +464,12 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (returnTypeFromRp != null) {
|
||||
if (returnTypeFromAnnotation != null && returnTypeFromAnnotation != IResource.class) {
|
||||
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type "
|
||||
+ returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type " + returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName()
|
||||
+ " (or a subclass of it) per IResourceProvider contract");
|
||||
}
|
||||
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type "
|
||||
+ returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return " + returnTypeFromRp.getCanonicalName()
|
||||
+ " (or a subclass of it) per IResourceProvider contract");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type " + returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return "
|
||||
+ returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
|
||||
}
|
||||
returnType = returnTypeFromAnnotation;
|
||||
} else {
|
||||
|
@ -460,8 +478,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
} else {
|
||||
if (returnTypeFromAnnotation != IResource.class) {
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
|
||||
+ " returns " + toLogString(returnTypeFromAnnotation) + " according to annotation - Must return a resource type");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromAnnotation)
|
||||
+ " according to annotation - Must return a resource type");
|
||||
}
|
||||
returnType = returnTypeFromAnnotation;
|
||||
} else {
|
||||
|
@ -572,8 +590,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (obj1 == null) {
|
||||
obj1 = object;
|
||||
} else {
|
||||
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @"
|
||||
+ obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
|
||||
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @" + obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -588,18 +605,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
||||
*/
|
||||
private static volatile IRequestReader ourRequestReader;
|
||||
|
||||
/**
|
||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
||||
*/
|
||||
private static interface IRequestReader {
|
||||
InputStream getInputStream(RequestDetails theRequestDetails) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
||||
*/
|
||||
|
@ -620,4 +625,11 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
||||
*/
|
||||
private static interface IRequestReader {
|
||||
InputStream getInputStream(RequestDetails theRequestDetails) throws IOException;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private int myResourceParameterIndex;
|
||||
private String myResourceName;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
private Integer myIdParamIndex;
|
||||
private String myResourceName;
|
||||
private int myResourceParameterIndex;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
|
||||
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
|
||||
super(theMethod, theContext, theMethodAnnotation, theProvider);
|
||||
|
|
|
@ -99,7 +99,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
myMethodReturnType = MethodReturnTypeEnum.LIST_OF_RESOURCES;
|
||||
Class<?> collectionType = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
|
||||
if (collectionType != null) {
|
||||
if (!Object.class.equals(collectionType) && !IResource.class.isAssignableFrom(collectionType)) {
|
||||
if (!Object.class.equals(collectionType) && !IBaseResource.class.isAssignableFrom(collectionType)) {
|
||||
throw new ConfigurationException("Method " + theMethod.getDeclaringClass().getSimpleName() + "#" + theMethod.getName() + " returns an invalid collection generic type: "
|
||||
+ collectionType);
|
||||
}
|
||||
|
|
|
@ -71,8 +71,10 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
* Server FHIR Provider which serves the conformance statement for a RESTful server implementation
|
||||
*
|
||||
* <p>
|
||||
* Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is always returned unless {@link #setCache(boolean)} is called with a value of
|
||||
* <code>false</code>. This means that if you are adding anything to the returned conformance instance on each call you should call <code>setCache(false)</code> in your provider constructor.
|
||||
* Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is
|
||||
* always returned unless {@link #setCache(boolean)} is called with a value of <code>false</code>. This means that if
|
||||
* you are adding anything to the returned conformance instance on each call you should call
|
||||
* <code>setCache(false)</code> in your provider constructor.
|
||||
* </p>
|
||||
*/
|
||||
public class ServerConformanceProvider implements IServerConformanceProvider<Conformance> {
|
||||
|
@ -87,8 +89,9 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The
|
||||
* value defaults to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
* Gets the value of the "publisher" that will be placed in the generated conformance statement. As this is a
|
||||
* mandatory element, the value should not be null (although this is not enforced). The value defaults to
|
||||
* "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
*/
|
||||
public String getPublisher() {
|
||||
return myPublisher;
|
||||
|
@ -107,7 +110,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
retVal.setFhirVersion("0.5.0"); // TODO: pull from model
|
||||
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser
|
||||
// needs to be modified to actually allow it
|
||||
// needs to be modified to actually allow it
|
||||
|
||||
retVal.getImplementation().setDescription(myRestfulServer.getImplementationDescription());
|
||||
retVal.getSoftware().setName(myRestfulServer.getServerName());
|
||||
|
@ -172,6 +175,22 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextMethodBinding.isSupportsConditional()) {
|
||||
switch (resOp) {
|
||||
case CREATE:
|
||||
resource.setConditionalCreate(true);
|
||||
break;
|
||||
case DELETE:
|
||||
resource.setConditionalDelete(true);
|
||||
break;
|
||||
case UPDATE:
|
||||
resource.setConditionalUpdate(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,8 +405,9 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The
|
||||
* value defaults to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
* Sets the value of the "publisher" that will be placed in the generated conformance statement. As this is a
|
||||
* mandatory element, the value should not be null (although this is not enforced). The value defaults to
|
||||
* "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
*/
|
||||
public void setPublisher(String thePublisher) {
|
||||
myPublisher = thePublisher;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -26,9 +23,15 @@ import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.SystemRestfulInteractionEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.TypeRestfulInteractionEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.History;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
|
@ -36,84 +39,35 @@ import ca.uhn.fhir.rest.annotation.OperationParam;
|
|||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchParameter;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
|
||||
|
||||
public class ServerConformanceProviderDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerConformanceProviderDstu2Test.class);
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerConformanceProviderDstu2Test.class);
|
||||
|
||||
@Test
|
||||
public void testSearchParameterDocumentation() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new SearchProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
boolean found=false;
|
||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||
found=true;
|
||||
}
|
||||
}
|
||||
assertTrue(found);
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
|
||||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
|
||||
private HttpServletRequest createHttpServletRequest() {
|
||||
HttpServletRequest req = mock(HttpServletRequest.class);
|
||||
when(req.getRequestURI()).thenReturn("/FhirStorm/fhir/Patient/_search");
|
||||
when(req.getServletPath()).thenReturn("/fhir");
|
||||
when(req.getRequestURL()).thenReturn(new StringBuffer().append("http://fhirstorm.dyndns.org:8080/FhirStorm/fhir/Patient/_search"));
|
||||
when(req.getContextPath()).thenReturn("/FhirStorm");
|
||||
return req;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationDocumentation() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new SearchProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
boolean found=false;
|
||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||
found=true;
|
||||
}
|
||||
}
|
||||
assertTrue(found);
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
|
||||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
|
||||
private ServletConfig createServletConfig() {
|
||||
ServletConfig sc = mock(ServletConfig.class);
|
||||
when(sc.getServletContext()).thenReturn(null);
|
||||
return sc;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -135,10 +89,10 @@ public class ServerConformanceProviderDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testValidateGeneratedStatement() throws Exception {
|
||||
public void testInstanceHistorySupported() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new MultiOptionalProvider());
|
||||
rs.setProviders(new InstanceHistoryProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
@ -146,12 +100,13 @@ public class ServerConformanceProviderDstu2Test {
|
|||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertTrue(ourCtx.newValidator().validateWithResult(conformance).isSuccessful());
|
||||
conf = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(conformance);
|
||||
assertThat(conf, containsString("<interaction><code value=\"" + TypeRestfulInteractionEnum.HISTORY_INSTANCE.getCode() + "\"/></interaction>"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultiOptionalDocumentation() throws Exception {
|
||||
|
||||
|
@ -163,7 +118,7 @@ public class ServerConformanceProviderDstu2Test {
|
|||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
boolean found=false;
|
||||
boolean found = false;
|
||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||
|
@ -171,7 +126,7 @@ public class ServerConformanceProviderDstu2Test {
|
|||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||
assertEquals("The patient's identifier", param.getDescription());
|
||||
found=true;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,6 +140,69 @@ public class ServerConformanceProviderDstu2Test {
|
|||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationDocumentation() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new SearchProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
boolean found = false;
|
||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
assertTrue(found);
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
|
||||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderWithRequiredAndOptional() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new ProviderWithRequiredAndOptional());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
Rest rest = conformance.getRestFirstRep();
|
||||
RestResource res = rest.getResourceFirstRep();
|
||||
assertEquals("DiagnosticReport", res.getType());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_SUBJECT, res.getSearchParam().get(0).getName());
|
||||
assertEquals("identifier", res.getSearchParam().get(0).getChain().get(0).getValue());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_NAME, res.getSearchParam().get(2).getName());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_DATE, res.getSearchParam().get(1).getName());
|
||||
|
||||
assertEquals(1, res.getSearchInclude().size());
|
||||
assertEquals("DiagnosticReport.result", res.getSearchIncludeFirstRep().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAndVReadSupported() throws Exception {
|
||||
|
||||
|
@ -224,11 +242,12 @@ public class ServerConformanceProviderDstu2Test {
|
|||
assertThat(conf, not(containsString("<interaction><code value=\"vread\"/></interaction>")));
|
||||
assertThat(conf, containsString("<interaction><code value=\"read\"/></interaction>"));
|
||||
}
|
||||
@Test
|
||||
public void testProviderWithRequiredAndOptional() throws Exception {
|
||||
|
||||
@Test
|
||||
public void testConditionalOperations() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new ProviderWithRequiredAndOptional());
|
||||
rs.setProviders(new ConditionalProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
@ -239,72 +258,132 @@ public class ServerConformanceProviderDstu2Test {
|
|||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
Rest rest = conformance.getRestFirstRep();
|
||||
RestResource res = rest.getResourceFirstRep();
|
||||
assertEquals("DiagnosticReport", res.getType());
|
||||
RestResource res = conformance.getRestFirstRep().getResourceFirstRep();
|
||||
assertEquals("Patient", res.getType());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_SUBJECT , res.getSearchParam().get(0).getName());
|
||||
assertEquals("identifier", res.getSearchParam().get(0).getChain().get(0).getValue());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_NAME, res.getSearchParam().get(2).getName());
|
||||
|
||||
assertEquals(DiagnosticReport.SP_DATE, res.getSearchParam().get(1).getName());
|
||||
|
||||
assertEquals(1,res.getSearchInclude().size());
|
||||
assertEquals("DiagnosticReport.result", res.getSearchIncludeFirstRep().getValue());
|
||||
assertTrue(res.getConditionalCreate());
|
||||
assertTrue(res.getConditionalDelete());
|
||||
assertTrue(res.getConditionalUpdate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonConditionalOperations() throws Exception {
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class SearchProvider {
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new NonConditionalProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(
|
||||
@Description(shortDefinition = "The patient's identifier (MRN or other card number)")
|
||||
@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
RestResource res = conformance.getRestFirstRep().getResourceFirstRep();
|
||||
assertEquals("Patient", res.getType());
|
||||
|
||||
assertNull(res.getConditionalCreate());
|
||||
assertNull(res.getConditionalDelete());
|
||||
assertNull(res.getConditionalUpdate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchParameterDocumentation() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new SearchProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
boolean found = false;
|
||||
Collection<ResourceBinding> resourceBindings = rs.getResourceBindings();
|
||||
for (ResourceBinding resourceBinding : resourceBindings) {
|
||||
if (resourceBinding.getResourceName().equals("Patient")) {
|
||||
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
|
||||
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
|
||||
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next();
|
||||
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
assertTrue(found);
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
|
||||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class VreadProvider {
|
||||
@Test
|
||||
public void testSystemHistorySupported() throws Exception {
|
||||
|
||||
@Read(version=true)
|
||||
public Patient readPatient(
|
||||
@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new SystemHistoryProvider());
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(
|
||||
@Description(shortDefinition = "The patient's identifier (MRN or other card number)")
|
||||
@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
}
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
conf = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(conformance);
|
||||
assertThat(conf, containsString("<interaction><code value=\"" + SystemRestfulInteractionEnum.HISTORY_SYSTEM.getCode() + "\"/></interaction>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class ReadProvider {
|
||||
@Test
|
||||
public void testTypeHistorySupported() throws Exception {
|
||||
|
||||
@Read(version=false)
|
||||
public Patient readPatient(
|
||||
@IdParam IdDt theId) {
|
||||
return null;
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new TypeHistoryProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
conf = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(conformance);
|
||||
assertThat(conf, containsString("<interaction><code value=\"" + TypeRestfulInteractionEnum.HISTORY_TYPE.getCode() + "\"/></interaction>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateGeneratedStatement() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer(ourCtx);
|
||||
rs.setProviders(new MultiOptionalProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(createServletConfig());
|
||||
|
||||
Conformance conformance = sc.getServerConformance(createHttpServletRequest());
|
||||
|
||||
assertTrue(ourCtx.newValidator().validateWithResult(conformance).isSuccessful());
|
||||
}
|
||||
|
||||
public static class InstanceHistoryProvider implements IResourceProvider {
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(
|
||||
@Description(shortDefinition = "The patient's identifier (MRN or other card number)")
|
||||
@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
@History
|
||||
public List<IBaseResource> history(@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -316,27 +395,7 @@ public class ServerConformanceProviderDstu2Test {
|
|||
public static class MultiOptionalProvider {
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(
|
||||
@Description(shortDefinition = "The patient's identifier")
|
||||
@OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier,
|
||||
@Description(shortDefinition = "The patient's name")
|
||||
@OptionalParam(name=Patient.SP_NAME) StringDt theName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class ProviderWithRequiredAndOptional {
|
||||
|
||||
@Description(shortDefinition="This is a search for stuff!")
|
||||
@Search
|
||||
public List<DiagnosticReport> findDiagnosticReportsByPatient (
|
||||
@RequiredParam(name=DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId,
|
||||
@OptionalParam(name=DiagnosticReport.SP_NAME) TokenOrListParam theNames,
|
||||
@OptionalParam(name=DiagnosticReport.SP_DATE) DateRangeParam theDateRange,
|
||||
@IncludeParam(allow= {"DiagnosticReport.result"}) Set<Include> theIncludes
|
||||
) throws Exception {
|
||||
public Patient findPatient(@Description(shortDefinition = "The patient's identifier") @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier, @Description(shortDefinition = "The patient's name") @OptionalParam(name = Patient.SP_NAME) StringDt theName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -344,12 +403,8 @@ public class ServerConformanceProviderDstu2Test {
|
|||
|
||||
public static class ProviderWithExtendedOperationReturningBundle implements IResourceProvider {
|
||||
|
||||
@Operation(name="everything", idempotent=true)
|
||||
public ca.uhn.fhir.rest.server.IBundleProvider everything(
|
||||
javax.servlet.http.HttpServletRequest theServletRequest,
|
||||
@IdParam ca.uhn.fhir.model.primitive.IdDt theId,
|
||||
@OperationParam(name="start") DateDt theStart,
|
||||
@OperationParam(name="end") DateDt theEnd) {
|
||||
@Operation(name = "everything", idempotent = true)
|
||||
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -360,19 +415,132 @@ public class ServerConformanceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
private HttpServletRequest createHttpServletRequest() {
|
||||
HttpServletRequest req = mock(HttpServletRequest.class);
|
||||
when(req.getRequestURI()).thenReturn("/FhirStorm/fhir/Patient/_search");
|
||||
when(req.getServletPath()).thenReturn("/fhir");
|
||||
when(req.getRequestURL()).thenReturn(new StringBuffer().append("http://fhirstorm.dyndns.org:8080/FhirStorm/fhir/Patient/_search"));
|
||||
when(req.getContextPath()).thenReturn("/FhirStorm");
|
||||
return req;
|
||||
public static class ProviderWithRequiredAndOptional {
|
||||
|
||||
@Description(shortDefinition = "This is a search for stuff!")
|
||||
@Search
|
||||
public List<DiagnosticReport> findDiagnosticReportsByPatient(@RequiredParam(name = DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId, @OptionalParam(name = DiagnosticReport.SP_NAME) TokenOrListParam theNames,
|
||||
@OptionalParam(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange, @IncludeParam(allow = { "DiagnosticReport.result" }) Set<Include> theIncludes) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ServletConfig createServletConfig() {
|
||||
ServletConfig sc = mock(ServletConfig.class);
|
||||
when (sc.getServletContext()).thenReturn(null);
|
||||
return sc;
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class ReadProvider {
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(@Description(shortDefinition = "The patient's identifier (MRN or other card number)") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Read(version = false)
|
||||
public Patient readPatient(@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class SearchProvider {
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(@Description(shortDefinition = "The patient's identifier (MRN or other card number)") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SystemHistoryProvider {
|
||||
|
||||
@History
|
||||
public List<IBaseResource> history() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TypeHistoryProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@History
|
||||
public List<IBaseResource> history() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ConditionalProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam Patient thePatient, @ConditionalUrlParam String theConditionalUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam IdDt theId, @ResourceParam Patient thePatient, @ConditionalUrlParam String theConditionalUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam IdDt theId, @ConditionalUrlParam String theConditionalUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class NonConditionalProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam Patient thePatient) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class VreadProvider {
|
||||
|
||||
@Search(type = Patient.class)
|
||||
public Patient findPatient(@Description(shortDefinition = "The patient's identifier (MRN or other card number)") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient readPatient(@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
and Bundle.entry.base is empty, it will now be
|
||||
automatically set by the parser.
|
||||
</action>
|
||||
<action type="add">
|
||||
<action type="add" issue="179">
|
||||
Add fluent client method for validate operation, and support the
|
||||
new DSTU2 style extended operation for $validate if the client is
|
||||
in DSTU2 mode. Thanks to Eric from the FHIR Skype Implementers chat for
|
||||
|
@ -105,7 +105,7 @@
|
|||
<action type="add">
|
||||
Server in DSTU2 mode now indicates that whether it has support for Transaction operation or not. Thanks to Kevin Paschke for pointing out that this wasn't working!
|
||||
</action>
|
||||
<action type="add">
|
||||
<action type="add" issue="166">
|
||||
Questionnaire.title now gets correctly indexed in JPA server (it has no path, so it is a special case)
|
||||
</action>
|
||||
<action type="add">
|
||||
|
@ -133,6 +133,10 @@
|
|||
<action type="fix">
|
||||
JPA server supports _count parameter in transaction containing search URL (nested search)
|
||||
</action>
|
||||
<action type="fix">
|
||||
DSTU2 servers now indicate support for conditional create/update/delete in their
|
||||
conformance statement.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.0" date="2015-May-8">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue