mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
Add validate method
This commit is contained in:
parent
15ae763313
commit
6877c0628e
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import 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.rest.server.IResourceProvider;
|
||||
|
||||
/**
|
||||
* RESTful method annotation to be used for the FHIR
|
||||
* <a href="http://hl7.org/implement/standards/fhir/http.html#validate">validate</a> method.
|
||||
*
|
||||
* <p>
|
||||
* Validate is used to accept a resource, and test whether it would be acceptable for
|
||||
* storing (e.g. using an update or create method)
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value=ElementType.METHOD)
|
||||
public @interface Validate {
|
||||
|
||||
/**
|
||||
* The return type for this method. This generally does not need
|
||||
* to be populated for a server implementation (using a {@link IResourceProvider},
|
||||
* since resource providers will return only one resource type per class,
|
||||
* but generally does need to be populated for client implementations.
|
||||
*/
|
||||
// NB: Read, Search (maybe others) share this annotation, so update the javadocs everywhere
|
||||
Class<? extends IResource> type() default IResource.class;
|
||||
|
||||
}
|
@ -51,6 +51,7 @@ import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
@ -139,8 +140,9 @@ public abstract class BaseMethodBinding {
|
||||
Update update = theMethod.getAnnotation(Update.class);
|
||||
Delete delete = theMethod.getAnnotation(Delete.class);
|
||||
History history = theMethod.getAnnotation(History.class);
|
||||
Validate validate = theMethod.getAnnotation(Validate.class);
|
||||
// ** if you add another annotation above, also add it to the next line:
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history)) {
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -188,6 +190,8 @@ public abstract class BaseMethodBinding {
|
||||
returnTypeFromAnnotation = create.type();
|
||||
} else if (update != null) {
|
||||
returnTypeFromAnnotation = update.type();
|
||||
} else if (validate != null) {
|
||||
returnTypeFromAnnotation = validate.type();
|
||||
}
|
||||
|
||||
if (returnTypeFromRp != null) {
|
||||
@ -232,6 +236,8 @@ public abstract class BaseMethodBinding {
|
||||
return new DeleteMethodBinding(theMethod, theContext, theProvider);
|
||||
} else if (history != null) {
|
||||
return new HistoryMethodBinding(theMethod, theContext, theProvider);
|
||||
} else if (validate != null) {
|
||||
return new ValidateMethodBinding(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -50,7 +49,6 @@ import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingUtil;
|
||||
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;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
@ -220,12 +218,22 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
||||
if (!getResourceName().equals(theRequest.getResourceName())) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.isNotBlank(theRequest.getOperation())) {
|
||||
if (getMatchingOperation() == null && StringUtils.isNotBlank(theRequest.getOperation())) {
|
||||
return false;
|
||||
}
|
||||
if (getMatchingOperation() != null && !getMatchingOperation().equals(theRequest.getOperation())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* For servers, this method will match only incoming requests
|
||||
* that match the given operation, or which have no operation in the
|
||||
* URL if this method returns null.
|
||||
*/
|
||||
protected abstract String getMatchingOperation();
|
||||
|
||||
/**
|
||||
* Subclasses may override to allow a void method return type, which is allowable for some methods (e.g. delete)
|
||||
*/
|
||||
|
@ -41,7 +41,6 @@ import ca.uhn.fhir.rest.server.EncodingUtil;
|
||||
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.UnprocessableEntityException;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private int myResourceParameterIndex;
|
||||
@ -63,8 +62,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
||||
}
|
||||
|
||||
if (resourceParameter == null) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with @"
|
||||
+ ResourceParam.class.getSimpleName());
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with @" + ResourceParam.class.getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
@ -129,14 +127,20 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
||||
|
||||
theServer.addHapiHeader(theResponse);
|
||||
|
||||
theResponse.setContentType(Constants.CT_TEXT);
|
||||
|
||||
if (response != null && response.getOperationOutcome() != null) {
|
||||
theResponse.setContentType(encoding.getResourceContentType());
|
||||
Writer writer = theResponse.getWriter();
|
||||
try {
|
||||
writer.append("Resource has been created");
|
||||
parser.encodeResourceToWriter(response.getOperationOutcome(), writer);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
} else {
|
||||
theResponse.setContentType(Constants.CT_TEXT);
|
||||
Writer writer = theResponse.getWriter();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
// getMethod().in
|
||||
}
|
||||
|
||||
|
@ -64,4 +64,9 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
|
||||
return new PostClientInvocation(getContext(), resource, urlExtension.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMatchingOperation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -143,4 +143,11 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
||||
theParams[myIdParameterIndex] = new IdDt(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getMatchingOperation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ package ca.uhn.fhir.rest.method;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -36,11 +35,10 @@ 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.rest.client.GetClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
@ -134,6 +132,10 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
||||
ourLog.trace("Method {} doesn't match because request type is POST but operation is not _search: {}", theRequest.getId(), theRequest.getOperation());
|
||||
return false;
|
||||
}
|
||||
if (theRequest.getRequestType() != RequestType.GET && theRequest.getRequestType() != RequestType.POST) {
|
||||
ourLog.trace("Method {} doesn't match because request type is {}", theRequest.getOperation());
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<String> methodParamsTemp = new HashSet<String>();
|
||||
for (int i = 0; i < this.myParameters.size(); i++) {
|
||||
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.method;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
@ -41,7 +41,6 @@ import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.PutClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
@ -136,4 +135,10 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
||||
return Collections.singleton(RequestType.PUT);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getMatchingOperation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
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.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.PutClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
class ValidateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
public ValidateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(theMethod, theContext, Validate.class, theProvider);
|
||||
|
||||
myIdParameterIndex = Util.findIdParameterIndex(theMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return RestfulOperationTypeEnum.VALIDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationSystemEnum getSystemOperationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
if (myIdParameterIndex != null) {
|
||||
theParams[myIdParameterIndex] = theRequest.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseClientInvocation createClientInvocation(Object[] theArgs, IResource resource, String resourceName) {
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
urlExtension.append(Constants.PARAM_VALIDATE);
|
||||
|
||||
if (myIdParameterIndex != null) {
|
||||
IdDt idDt = (IdDt) theArgs[myIdParameterIndex];
|
||||
if (idDt != null && idDt.isEmpty() == false) {
|
||||
String id = idDt.getValue();
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(id);
|
||||
}
|
||||
}
|
||||
|
||||
PutClientInvocation retVal = new PutClientInvocation(getContext(), resource, urlExtension.toString());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean allowVoidReturnType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<RequestType> provideAllowableRequestTypes() {
|
||||
return Collections.singleton(RequestType.POST);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getMatchingOperation() {
|
||||
return Constants.PARAM_VALIDATE;
|
||||
}
|
||||
|
||||
}
|
@ -59,6 +59,7 @@ public class Constants {
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String HEADER_LAST_MODIFIED = "Last-Modified";
|
||||
public static final String HEADER_LAST_MODIFIED_LOWERCASE = HEADER_LAST_MODIFIED.toLowerCase();
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
|
||||
static {
|
||||
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
||||
|
@ -20,6 +20,14 @@ package ca.uhn.fhir.rest.server.exceptions;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* RESTful method exception which corresponds to the <b>HTTP 400 Bad Request</b> status.
|
||||
* This status indicates that the client's message was invalid (e.g. not a valid FHIR Resource
|
||||
* per the specifications), as opposed to the {@link InvalidRequestException} which indicates
|
||||
* that data does not pass business rule validation on the server.
|
||||
*
|
||||
* @see UnprocessableEntityException Which should be used for business level validation failures
|
||||
*/
|
||||
public class InvalidRequestException extends BaseServerResponseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -28,6 +28,8 @@ import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
* <p>
|
||||
* This exception will generally contain an {@link OperationOutcome} instance which details the failure.
|
||||
* </p>
|
||||
*
|
||||
* @see InvalidRequestException Which corresponds to an <b>HTTP 400 Bad Request</b> failure
|
||||
*/
|
||||
public class UnprocessableEntityException extends BaseServerResponseException {
|
||||
|
||||
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
@ -38,6 +39,7 @@ 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.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.ITestClient;
|
||||
@ -307,6 +309,7 @@ public MethodOutcome createPatient(@ResourceParam Patient thePatient) {
|
||||
}
|
||||
//END SNIPPET: create
|
||||
|
||||
|
||||
//START SNIPPET: createClient
|
||||
@Create
|
||||
public abstract MethodOutcome createNewPatient(@ResourceParam Patient thePatient);
|
||||
@ -369,6 +372,39 @@ return retVal;
|
||||
|
||||
|
||||
|
||||
//START SNIPPET: validate
|
||||
@Validate
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient) {
|
||||
|
||||
/*
|
||||
* Actually do our validation: The UnprocessableEntityException
|
||||
* results in an HTTP 422, which is appropriate for business rule failure
|
||||
*/
|
||||
if (thePatient.getIdentifierFirstRep().isEmpty()) {
|
||||
/* It is also possible to pass an OperationOutcome resource
|
||||
* to the UnprocessableEntityException if you want to return
|
||||
* a custom populated OperationOutcome. Otherwise, a simple one
|
||||
* is created using the string supplied below.
|
||||
*/
|
||||
throw new UnprocessableEntityException("No identifier supplied");
|
||||
}
|
||||
|
||||
// This method returns a MethodOutcome object
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
|
||||
// You may also add an OperationOutcome resource to return
|
||||
// This part is optional though:
|
||||
OperationOutcome outcome = new OperationOutcome();
|
||||
outcome.addIssue().setSeverity(IssueSeverityEnum.WARNING).setDetails("One minor issue detected");
|
||||
retVal.setOperationOutcome(outcome);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
//END SNIPPET: validate
|
||||
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws DataFormatException, IOException {
|
||||
//nothing
|
||||
}
|
||||
|
@ -15,12 +15,14 @@
|
||||
method pattern, with one key difference: A client
|
||||
is defined using annotated methods on an interface
|
||||
which are used to retrieve resources,
|
||||
whereas a server requires concrete method implementations
|
||||
whereas a server requires concrete method
|
||||
implementations
|
||||
to actually provide those resources.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unless otherwise specified, the examples below show <b>server</b>
|
||||
Unless otherwise specified, the examples below show
|
||||
<b>server</b>
|
||||
implementations, but client methods will follow the same patterns.
|
||||
</p>
|
||||
|
||||
@ -89,8 +91,8 @@
|
||||
<td>
|
||||
<a href="#instance_update">Type - Search</a>
|
||||
<macro name="toc">
|
||||
<param name="section" value="7"/>
|
||||
<param name="fromDepth" value="2"/>
|
||||
<param name="section" value="7" />
|
||||
<param name="fromDepth" value="2" />
|
||||
</macro>
|
||||
</td>
|
||||
<td>
|
||||
@ -157,7 +159,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a name="instance_read"/>
|
||||
<a name="instance_read" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -168,7 +170,9 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/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
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>
|
||||
annotation, and has a single parameter annotated with the
|
||||
@ -182,11 +186,12 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient/111</code>
|
||||
</p>
|
||||
|
||||
<a name="instance_vread"/>
|
||||
<a name="instance_vread" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -197,7 +202,9 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/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
|
||||
like a "read" operation, but with a second
|
||||
parameter annotated with the
|
||||
@ -211,11 +218,12 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient/111/_history/2</code>
|
||||
</p>
|
||||
|
||||
<a name="instance_update"/>
|
||||
<a name="instance_update" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -226,7 +234,9 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#update"><b>update</b></a>
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#update">
|
||||
<b>update</b>
|
||||
</a>
|
||||
operation updates a specific resource instance (using its ID), and optionally
|
||||
accepts a version ID as well (which can be used to detect version conflicts).
|
||||
</p>
|
||||
@ -245,7 +255,8 @@
|
||||
</p>
|
||||
<p>
|
||||
Update methods must return an object of type
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a>. This
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a>
|
||||
. This
|
||||
object contains the identity of the created resource.
|
||||
</p>
|
||||
<p>
|
||||
@ -259,7 +270,8 @@
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method (this would be invoked using an HTTP PUT,
|
||||
with the resource in the PUT body):<br/>
|
||||
with the resource in the PUT body):
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient</code>
|
||||
</p>
|
||||
|
||||
@ -283,7 +295,7 @@
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="instance_delete"/>
|
||||
<a name="instance_delete" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -294,7 +306,9 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#delete"><b>delete</b></a>
|
||||
<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>
|
||||
@ -311,25 +325,34 @@
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>void</b>: This method may return <code>void</code>, in which case
|
||||
<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>,
|
||||
<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/>
|
||||
Example URL to invoke this method (HTTP DELETE):
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient/111</code>
|
||||
</p>
|
||||
|
||||
<a name="type_create"/>
|
||||
<a name="type_create" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -340,7 +363,9 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#create"><b>create</b></a>
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#create">
|
||||
<b>create</b>
|
||||
</a>
|
||||
operation saves a new resource to the server, allowing the server to
|
||||
give that resource an ID and version ID.
|
||||
</p>
|
||||
@ -353,7 +378,8 @@
|
||||
</p>
|
||||
<p>
|
||||
Create methods must return an object of type
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a>. This
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a>
|
||||
. This
|
||||
object contains the identity of the created resource.
|
||||
</p>
|
||||
<p>
|
||||
@ -367,7 +393,8 @@
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method (this would be invoked using an HTTP POST,
|
||||
with the resource in the POST body):<br/>
|
||||
with the resource in the POST body):
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient</code>
|
||||
</p>
|
||||
|
||||
@ -381,7 +408,7 @@
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="type_search"/>
|
||||
<a name="type_search" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -392,7 +419,10 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/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.
|
||||
</p>
|
||||
|
||||
@ -401,7 +431,8 @@
|
||||
<p>
|
||||
The following example shows a search with no parameters. This operation
|
||||
should return all resources of a given type (this obviously doesn't make
|
||||
sense in all contexts, but does for some resource types).
|
||||
sense in all contexts, but
|
||||
does for some resource types).
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
@ -410,7 +441,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient</code>
|
||||
</p>
|
||||
|
||||
@ -422,14 +454,16 @@
|
||||
to your search method and tag these parameters as either
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/RequiredParam.html">@RequiredParam</a>
|
||||
or
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/OptionalParam.html">@OptionalParam</a>.
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/OptionalParam.html">@OptionalParam</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This annotation takes a "name" parameter which specifies the parameter's
|
||||
name (as it will appear in the search URL). FHIR defines standardized parameter
|
||||
names for each resource, and these are available as constants on the
|
||||
individual HAPI resource classes.
|
||||
individual HAPI resource
|
||||
classes.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
@ -438,7 +472,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient?family=SMITH</code>
|
||||
</p>
|
||||
|
||||
@ -458,7 +493,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient?identifier=urn:foo|7000135</code>
|
||||
</p>
|
||||
|
||||
@ -469,15 +505,20 @@
|
||||
Search methods may take multiple parameters, and these parameters
|
||||
may be optional. To add a second required parameter, annotate the
|
||||
parameter with
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/RequiredParam.html">@RequiredParam</a>.
|
||||
To add an optional parameter (which will be passed in as <code>null</code> if no value
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/RequiredParam.html">@RequiredParam</a>
|
||||
.
|
||||
To add an optional parameter (which will be passed in as
|
||||
<code>null</code>
|
||||
if no value
|
||||
is supplied), annotate the method with
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/OptionalParam.html">@OptionalParam</a>.
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/OptionalParam.html">@OptionalParam</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may annotate a method with any combination of as many @RequiredParam and as many @OptionalParam
|
||||
parameters as you want. It is valid to have only @RequiredParam parameters, or
|
||||
parameters as you want. It is valid to have only @RequiredParam
|
||||
parameters, or
|
||||
only @OptionalParam parameters, or any combination of the two.
|
||||
</p>
|
||||
|
||||
@ -487,8 +528,10 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URLs to invoke this method:<br/>
|
||||
<code>http://fhir.example.com/Patient?family=SMITH</code><br/>
|
||||
Example URLs to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient?family=SMITH</code>
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient?family=SMITH&given=JOHN</code>
|
||||
</p>
|
||||
|
||||
@ -499,8 +542,10 @@
|
||||
<p>
|
||||
It is possible to accept multiple values of a single parameter
|
||||
as well. This is useful in cases when you want to return a list
|
||||
of resources with criteria matching a list of possible values.
|
||||
See the <a href="http://www.hl7.org/implement/standards/fhir/search.html#combining">FHIR Specification</a>
|
||||
of resources with criteria matching a list of
|
||||
possible values.
|
||||
See the
|
||||
<a href="http://www.hl7.org/implement/standards/fhir/search.html#combining">FHIR Specification</a>
|
||||
for more information.
|
||||
</p>
|
||||
|
||||
@ -510,12 +555,20 @@
|
||||
<ul>
|
||||
<li>
|
||||
Where a parameter may accept multiple comma separated values within a single value string
|
||||
(e.g. <code>?language=FR,NL</code>) this is treated as an <b>OR</b> relationship, and
|
||||
(e.g.
|
||||
<code>?language=FR,NL</code>
|
||||
) this is treated as an
|
||||
<b>OR</b>
|
||||
relationship, and
|
||||
the search should return elements matching either one or the other.
|
||||
</li>
|
||||
<li>
|
||||
Where a parameter may accept multiple value strings for the same parameter name
|
||||
(e.g. <code>?language=FR&language=NL</code>) this is treated as an <b>AND</b> relationship,
|
||||
(e.g.
|
||||
<code>?language=FR&language=NL</code>
|
||||
) this is treated as an
|
||||
<b>AND</b>
|
||||
relationship,
|
||||
and the search should return only elements matching both.
|
||||
</li>
|
||||
</ul>
|
||||
@ -535,7 +588,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Observation?name=urn:fakenames|123,urn:fakenames|456</code>
|
||||
</p>
|
||||
|
||||
@ -548,7 +602,9 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the section below on <a href="#DATE_RANGES">date ranges</a> for
|
||||
See the section below on
|
||||
<a href="#DATE_RANGES">date ranges</a>
|
||||
for
|
||||
one example of an AND parameter.
|
||||
</p>
|
||||
|
||||
@ -564,7 +620,9 @@
|
||||
|
||||
<p>
|
||||
Dates may be optionally prefixed with a qualifier. For example, the
|
||||
string <code>>=2011-01-02</code> means any date on or after 2011-01-02.
|
||||
string
|
||||
<code>>=2011-01-02</code>
|
||||
means any date on or after 2011-01-02.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -579,7 +637,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Observation?birthdate=>=2011-01-02</code>
|
||||
</p>
|
||||
|
||||
@ -594,7 +653,7 @@
|
||||
|
||||
</subsection>
|
||||
|
||||
<a name="DATE_RANGES"/>
|
||||
<a name="DATE_RANGES" />
|
||||
<subsection name="Date Parameters - Ranges">
|
||||
|
||||
<p>
|
||||
@ -604,15 +663,20 @@
|
||||
|
||||
<p>
|
||||
FHIR allows for multiple parameters with the same key, and interprets
|
||||
these as being an "AND" set. So, for example, a range of<br/>
|
||||
<code>DATE >= 2011-01-01</code> and <code>DATE < 2011-02-01</code><br/>
|
||||
these as being an "AND" set. So, for example, a range of
|
||||
<br />
|
||||
<code>DATE >= 2011-01-01</code>
|
||||
and
|
||||
<code>DATE < 2011-02-01</code>
|
||||
<br />
|
||||
can be interpreted as any date within January 2011.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following snippet shows how to accept such a range, and combines it
|
||||
with a specific identifier, which is a common scenario. (i.e. Give me a list
|
||||
of observations for a specific patient within a given date range)
|
||||
of observations for a
|
||||
specific patient within a given date range)
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="dateRange" />
|
||||
@ -620,7 +684,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Observation?subject.identifier=7000135&date=>=2011-01-01&date=<2011-02-01</code>
|
||||
</p>
|
||||
|
||||
@ -640,7 +705,8 @@
|
||||
<p>
|
||||
FHIR allows clients to request that specific linked resources be included
|
||||
as contained resources, which means that they will be "embedded" in a special
|
||||
container called "contained" within the parent resource.
|
||||
container called
|
||||
"contained" within the parent resource.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -654,7 +720,8 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/DiagnosticReport?subject.identifier=7000135&_include=DiagnosticReport.subject</code>
|
||||
</p>
|
||||
|
||||
@ -663,7 +730,9 @@
|
||||
<subsection name="Named Queries (_query)">
|
||||
|
||||
<p>
|
||||
FHIR supports <a href="http://www.hl7.org/implement/standards/fhir/search.html#advanced">named queries</a>,
|
||||
FHIR supports
|
||||
<a href="http://www.hl7.org/implement/standards/fhir/search.html#advanced">named queries</a>
|
||||
,
|
||||
which may have specific behaviour defined. The following example shows how to create a Search
|
||||
operation with a name.
|
||||
</p>
|
||||
@ -679,13 +748,14 @@
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient?_query=namedQuery1&someparam=value</code>
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
||||
<a name="type_validate"/>
|
||||
<a name="type_validate" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -695,10 +765,68 @@
|
||||
<section name="Type Level - Validate">
|
||||
|
||||
<p>
|
||||
Not yet implemented
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#validate">
|
||||
<b>validate</b>
|
||||
</a>
|
||||
tests whether a resource passes business validation, and would be
|
||||
acceptable for saving to a server (e.g. by a create or update method).
|
||||
</p>
|
||||
<p>
|
||||
Validate methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Validate.html">@Validate</a>
|
||||
annotation, and have a parameter annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/ResourceParam.html">@Resource</a>
|
||||
annotation. This parameter contains the resource instance to be created.
|
||||
</p>
|
||||
<p>
|
||||
Validate methods may optionally also have a parameter
|
||||
oftype IdDt annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/IdParam.html">@IdParam</a>
|
||||
annotation. This parameter contains the resource ID (see the
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#validation">FHIR specification</a>
|
||||
for details on how this is used)
|
||||
</p>
|
||||
<p>
|
||||
Validate methods must return normally if the resource validates successfully,
|
||||
or throw an
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/exceptions/UnprocessableEntityException.html">UnprocessableEntityException</a>
|
||||
or
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/exceptions/InvalidRequestException.html">InvalidRequestException</a>
|
||||
if the validation fails.
|
||||
</p>
|
||||
<p>
|
||||
Validate methods must return either:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>void</b>
|
||||
- The method should throw an exception for a validation failure, or return normally.
|
||||
</li>
|
||||
<li>
|
||||
An object of type
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/api/MethodOutcome.html">MethodOutcome</a>. The
|
||||
MethodOutcome may optionally be populated with an OperationOutcome resource, which
|
||||
will be returned to the client if it exists.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
The following snippet shows how to define a server validate method:
|
||||
</p>
|
||||
|
||||
<a name="system_conformance"/>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="validate" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method (this would be invoked using an HTTP POST,
|
||||
with the resource in the POST body):
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient/_validate</code>
|
||||
</p>
|
||||
|
||||
<a name="system_conformance" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -745,7 +873,8 @@
|
||||
|
||||
<p>
|
||||
Then use the standard
|
||||
<a href="doc_rest_client.html">RESTful Client</a> mechanism for instantiating
|
||||
<a href="doc_rest_client.html">RESTful Client</a>
|
||||
mechanism for instantiating
|
||||
a client:
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
@ -753,7 +882,7 @@
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<a name="system_transaction"/>
|
||||
<a name="system_transaction" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -766,7 +895,7 @@
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="system_search"/>
|
||||
<a name="system_search" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -779,7 +908,7 @@
|
||||
Not yet implemented
|
||||
</p>
|
||||
|
||||
<a name="history"/>
|
||||
<a name="history" />
|
||||
</section>
|
||||
|
||||
<!-- ****************************************************************** -->
|
||||
@ -790,10 +919,17 @@
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#history"><b>history</b></a>
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#history">
|
||||
<b>history</b>
|
||||
</a>
|
||||
operation retrieves a historical collection of all versions of a single resource
|
||||
<i>(instance history)</i>, all resources of a given type <i>(type history)</i>,
|
||||
or all resources of any type on a server <i>(server history)</i>.
|
||||
<i>(instance history)</i>
|
||||
, all resources of a given type
|
||||
<i>(type history)</i>
|
||||
,
|
||||
or all resources of any type on a server
|
||||
<i>(server history)</i>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
History methods must be annotated with the
|
||||
@ -803,16 +939,22 @@
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
For an <b>Instance History</b> method, the method must have a parameter
|
||||
For an
|
||||
<b>Instance History</b>
|
||||
method, the method must have a parameter
|
||||
annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/IdParam.html">@IdParam</a>
|
||||
annotation, indicating the ID of the resource for which to return history.
|
||||
</li>
|
||||
<li>
|
||||
For an <b>Type History</b> method, the method must not have any @IdParam parameter.
|
||||
For an
|
||||
<b>Type History</b>
|
||||
method, the method must not have any @IdParam parameter.
|
||||
</li>
|
||||
<li>
|
||||
For an <b>Server History</b> method, the method must not have any @IdParam parameter
|
||||
For an
|
||||
<b>Server History</b>
|
||||
method, the method must not have any @IdParam parameter
|
||||
and must not be found in a ResourceProvider definition.
|
||||
<!-- TODO: make ResourceProvider a link to a defintion of these on the RESTFul server page -->
|
||||
</li>
|
||||
|
@ -69,6 +69,7 @@ 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.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||
@ -855,6 +856,59 @@ public class ResfulServerMethodTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidate() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("FOO");
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
OperationOutcome oo = new FhirContext().newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||
assertEquals("it passed", oo.getIssueFirstRep().getDetails().getValue());
|
||||
|
||||
// Now should fail
|
||||
|
||||
patient = new Patient();
|
||||
patient.addName().addFamily("BAR");
|
||||
|
||||
httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
status = ourClient.execute(httpPost);
|
||||
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
oo = new FhirContext().newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||
assertEquals("it failed", oo.getIssueFirstRep().getDetails().getValue());
|
||||
|
||||
// Should fail with outcome
|
||||
|
||||
patient = new Patient();
|
||||
patient.addName().addFamily("BAZ");
|
||||
|
||||
httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
status = ourClient.execute(httpPost);
|
||||
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals("", responseContent);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWithVersion() throws Exception {
|
||||
|
||||
@ -973,6 +1027,22 @@ public class ResfulServerMethodTest {
|
||||
return new MethodOutcome(true, id, version);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient) {
|
||||
if (thePatient.getNameFirstRep().getFamilyFirstRep().getValueNotNull().equals("FOO")) {
|
||||
MethodOutcome methodOutcome = new MethodOutcome();
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDetails("it passed");
|
||||
methodOutcome.setOperationOutcome(oo);
|
||||
return methodOutcome;
|
||||
}
|
||||
if (thePatient.getNameFirstRep().getFamilyFirstRep().getValueNotNull().equals("BAR")) {
|
||||
throw new UnprocessableEntityException("it failed");
|
||||
}
|
||||
return new MethodOutcome();
|
||||
}
|
||||
|
||||
|
||||
private Patient createPatient1() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier();
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
146
hapi-fhir-structures-dstu/pom.xml.versionsBackup
Normal file
146
hapi-fhir-structures-dstu/pom.xml.versionsBackup
Normal file
@ -0,0 +1,146 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.3</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR Structures - DSTU (FHIR 0.80)</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>0.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>0.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>generate-structures</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<package>ca.uhn.fhir.model.dstu</package>
|
||||
<baseResourceNames>
|
||||
<!-- <baseResourceName>account</baseResourceName> -->
|
||||
<!-- <baseResourceName>activitydefinition-extensions</baseResourceName> -->
|
||||
<baseResourceName>adversereaction</baseResourceName>
|
||||
<baseResourceName>alert</baseResourceName>
|
||||
<baseResourceName>allergyintolerance</baseResourceName>
|
||||
<baseResourceName>appointmentresponse</baseResourceName>
|
||||
<baseResourceName>appointment</baseResourceName>
|
||||
<baseResourceName>availability</baseResourceName>
|
||||
<baseResourceName>careplan</baseResourceName>
|
||||
<baseResourceName>claim</baseResourceName>
|
||||
<baseResourceName>composition</baseResourceName>
|
||||
<baseResourceName>conceptmap</baseResourceName>
|
||||
<baseResourceName>condition</baseResourceName>
|
||||
<baseResourceName>conformance</baseResourceName>
|
||||
<baseResourceName>coverage</baseResourceName>
|
||||
<baseResourceName>deviceobservationreport</baseResourceName>
|
||||
<baseResourceName>device</baseResourceName>
|
||||
<baseResourceName>diagnosticorder</baseResourceName>
|
||||
<baseResourceName>diagnosticreport</baseResourceName>
|
||||
<baseResourceName>documentmanifest</baseResourceName>
|
||||
<baseResourceName>documentreference</baseResourceName>
|
||||
<baseResourceName>encounter</baseResourceName>
|
||||
<!-- <baseResourceName>familyhistory-genetics-profile</baseResourceName> -->
|
||||
<baseResourceName>familyhistory</baseResourceName>
|
||||
<baseResourceName>geneexpression</baseResourceName>
|
||||
<baseResourceName>geneticanalysis</baseResourceName>
|
||||
<baseResourceName>group</baseResourceName>
|
||||
<baseResourceName>gvfmeta</baseResourceName>
|
||||
<baseResourceName>gvfvariant</baseResourceName>
|
||||
<baseResourceName>imagingstudy</baseResourceName>
|
||||
<baseResourceName>immunizationrecommendation</baseResourceName>
|
||||
<baseResourceName>immunization</baseResourceName>
|
||||
<baseResourceName>list</baseResourceName>
|
||||
<baseResourceName>location</baseResourceName>
|
||||
<baseResourceName>media</baseResourceName>
|
||||
<baseResourceName>medicationadministration</baseResourceName>
|
||||
<baseResourceName>medicationdispense</baseResourceName>
|
||||
<baseResourceName>medicationprescription</baseResourceName>
|
||||
<baseResourceName>medication</baseResourceName>
|
||||
<baseResourceName>medicationstatement</baseResourceName>
|
||||
<baseResourceName>messageheader</baseResourceName>
|
||||
<baseResourceName>microarray</baseResourceName>
|
||||
<!-- <baseResourceName>namespace</baseResourceName> -->
|
||||
<baseResourceName>observation</baseResourceName>
|
||||
<baseResourceName>operationoutcome</baseResourceName>
|
||||
<baseResourceName>orderresponse</baseResourceName>
|
||||
<baseResourceName>order</baseResourceName>
|
||||
<baseResourceName>organization</baseResourceName>
|
||||
<baseResourceName>other</baseResourceName>
|
||||
<baseResourceName>patient</baseResourceName>
|
||||
<!--<baseResourceName>person</baseResourceName>-->
|
||||
<baseResourceName>practitioner</baseResourceName>
|
||||
<baseResourceName>procedure</baseResourceName>
|
||||
<baseResourceName>profile</baseResourceName>
|
||||
<!-- <baseResourceName>protocol</baseResourceName> -->
|
||||
<!-- <baseResourceName>provenance-extensions</baseResourceName> -->
|
||||
<baseResourceName>provenance</baseResourceName>
|
||||
<baseResourceName>query</baseResourceName>
|
||||
<!-- <baseResourceName>questionnaire-extensions</baseResourceName> -->
|
||||
<baseResourceName>questionnaire</baseResourceName>
|
||||
<baseResourceName>relatedperson</baseResourceName>
|
||||
<baseResourceName>remittance</baseResourceName>
|
||||
<!-- <baseResourceName>resource</baseResourceName> -->
|
||||
<baseResourceName>securityevent</baseResourceName>
|
||||
<!--<baseResourceName>sequence</baseResourceName>-->
|
||||
<baseResourceName>sequencinganalysis</baseResourceName>
|
||||
<baseResourceName>sequencinglab</baseResourceName>
|
||||
<baseResourceName>slot</baseResourceName>
|
||||
<baseResourceName>specimen</baseResourceName>
|
||||
<baseResourceName>substance</baseResourceName>
|
||||
<baseResourceName>supply</baseResourceName>
|
||||
<!--<baseResourceName>template</baseResourceName>-->
|
||||
<baseResourceName>test</baseResourceName>
|
||||
<baseResourceName>user</baseResourceName>
|
||||
<!-- <baseResourceName>valueset-extensions</baseResourceName> -->
|
||||
<baseResourceName>valueset</baseResourceName>
|
||||
<!--<baseResourceName>vcfmeta</baseResourceName>-->
|
||||
<!--<baseResourceName>vcfvariant</baseResourceName>-->
|
||||
</baseResourceNames>
|
||||
<buildDatatypes>true</buildDatatypes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven_javadoc_plugin_version}</version>
|
||||
<configuration>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
</project>
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.3</version>
|
||||
<version>0.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user