Add request/response validator interceptors
This commit is contained in:
parent
ccc71c3bd3
commit
685bd9345b
|
@ -3,11 +3,16 @@ package example;
|
|||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
|
||||
import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
|
||||
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ServletExamples {
|
||||
|
@ -38,6 +43,42 @@ public class ServletExamples {
|
|||
}
|
||||
// END SNIPPET: loggingInterceptor
|
||||
|
||||
// START SNIPPET: validatingInterceptor
|
||||
@WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server")
|
||||
public class ValidatingServerWithLogging extends RestfulServer {
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
|
||||
// ... define your resource providers here ...
|
||||
|
||||
// Create an interceptor to validate incoming requests
|
||||
RequestValidatingInterceptor requestInterceptor = new RequestValidatingInterceptor();
|
||||
|
||||
// Register a validator module (you could also use SchemaBaseValidator and/or SchematronBaseValidator)
|
||||
requestInterceptor.addValidatorModule(new FhirInstanceValidator());
|
||||
|
||||
requestInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
requestInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||
requestInterceptor.setResponseHeaderValue("Validation on ${line}: ${message} ${severity}");
|
||||
requestInterceptor.setResponseHeaderValueNoIssues("No issues detected");
|
||||
|
||||
// Now register the validating interceptor
|
||||
registerInterceptor(requestInterceptor);
|
||||
|
||||
// Create an interceptor to validate responses
|
||||
// This is configured in the same way as above
|
||||
ResponseValidatingInterceptor responseInterceptor = new ResponseValidatingInterceptor();
|
||||
responseInterceptor.addValidatorModule(new FhirInstanceValidator());
|
||||
responseInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
responseInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||
responseInterceptor.setResponseHeaderValue("Validation on ${line}: ${message} ${severity}");
|
||||
responseInterceptor.setResponseHeaderValueNoIssues("No issues detected");
|
||||
registerInterceptor(responseInterceptor);
|
||||
}
|
||||
|
||||
}
|
||||
// END SNIPPET: validatingInterceptor
|
||||
|
||||
// START SNIPPET: exceptionInterceptor
|
||||
@WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server")
|
||||
|
|
|
@ -38,6 +38,7 @@ public class MethodOutcome {
|
|||
* Constructor
|
||||
*/
|
||||
public MethodOutcome() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Set;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
|
@ -48,11 +49,13 @@ import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServer;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||
|
@ -64,8 +67,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
|
||||
if (!allowVoidReturnType()) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName()
|
||||
+ " method but it does not return " + MethodOutcome.class);
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName() + " method but it does not return " + MethodOutcome.class);
|
||||
} else if (theMethod.getReturnType() == void.class) {
|
||||
myReturnVoid = true;
|
||||
}
|
||||
|
@ -84,7 +86,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
protected abstract BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource resource);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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();
|
||||
|
||||
|
@ -109,51 +112,29 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
@Override
|
||||
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
|
||||
switch (theResponseStatusCode) {
|
||||
case Constants.STATUS_HTTP_200_OK:
|
||||
case Constants.STATUS_HTTP_201_CREATED:
|
||||
case Constants.STATUS_HTTP_204_NO_CONTENT:
|
||||
if (theResponseStatusCode >= 200 && theResponseStatusCode < 300) {
|
||||
if (myReturnVoid) {
|
||||
return null;
|
||||
}
|
||||
MethodOutcome retVal = MethodUtil.process2xxResponse(getContext(), getResourceName(), theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
||||
return retVal;
|
||||
default:
|
||||
} else {
|
||||
throw processNon2xxResponseAndReturnExceptionToThrow(theResponseStatusCode, theResponseMimeType, theResponseReader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
// if (requestContainsResource()) {
|
||||
// requestContents = parseIncomingServerResource(theRequest);
|
||||
// } else {
|
||||
// requestContents = null;
|
||||
// }
|
||||
|
||||
Object[] params = createParametersForServerRequest(theRequest);
|
||||
addParametersForServerRequest(theRequest, params);
|
||||
|
||||
|
||||
/*
|
||||
* No need to catch nd handle exceptions here, we already handle them one level up
|
||||
* including invoking interceptors on them
|
||||
* No need to catch and handle exceptions here, we already handle them one level up including invoking interceptors
|
||||
* on them
|
||||
*/
|
||||
MethodOutcome response;
|
||||
// try {
|
||||
response = (MethodOutcome) invokeServerMethod(theServer, theRequest, params);
|
||||
// } catch (InternalErrorException e) {
|
||||
// ourLog.error("Internal error during method invocation", e);
|
||||
// EncodingEnum encodingNotNull = RestfulServerUtils.determineResponseEncodingWithDefault(theServer, theRequest.getServletRequest());
|
||||
// streamOperationOutcome(e, theServer, encodingNotNull, servletResponse, theRequest);
|
||||
// return;
|
||||
// } catch (BaseServerResponseException e) {
|
||||
// ourLog.info("Exception during method invocation: " + e.getMessage());
|
||||
// EncodingEnum encodingNotNull = RestfulServerUtils.determineResponseEncodingWithDefault(theServer, theRequest.getServletRequest());
|
||||
// streamOperationOutcome(e, theServer, encodingNotNull, servletResponse, theRequest);
|
||||
// return;
|
||||
// }
|
||||
response = (MethodOutcome) invokeServerMethod(theServer, theRequest, params);
|
||||
|
||||
if (response != null && response.getId() != null && response.getId().hasResourceType()) {
|
||||
if (getContext().getResourceDefinition(response.getId().getResourceType()) == null) {
|
||||
|
@ -161,25 +142,17 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
}
|
||||
|
||||
IBaseResource outcome = response != null ? response.getOperationOutcome() : null;
|
||||
IBaseOperationOutcome outcome = response != null ? response.getOperationOutcome() : null;
|
||||
IBaseResource resource = response != null ? response.getResource() : null;
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, outcome);
|
||||
if (!continueProcessing) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return returnResponse(theRequest, response, outcome, resource);
|
||||
return returnResponse(theServer, theRequest, response, outcome, resource);
|
||||
}
|
||||
|
||||
|
||||
private int getOperationStatus(MethodOutcome response) {
|
||||
switch (getRestOperationType()) {
|
||||
case CREATE:
|
||||
if (response == null) {
|
||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName()
|
||||
+ " returned null, which is not allowed for create operation");
|
||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null, which is not allowed for create operation");
|
||||
}
|
||||
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
|
||||
return Constants.STATUS_HTTP_201_CREATED;
|
||||
|
@ -212,15 +185,14 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
}
|
||||
|
||||
private Object returnResponse(RequestDetails theRequest, MethodOutcome response, IBaseResource originalOutcome, IBaseResource resource) throws IOException {
|
||||
private Object returnResponse(IRestfulServer<?> theServer, RequestDetails theRequest, MethodOutcome response, IBaseResource originalOutcome, IBaseResource resource) throws IOException {
|
||||
boolean allowPrefer = false;
|
||||
int operationStatus = getOperationStatus(response);
|
||||
IBaseResource outcome = originalOutcome;
|
||||
|
||||
if(EnumSet.of(RestOperationTypeEnum.CREATE, RestOperationTypeEnum.UPDATE).contains(getRestOperationType())) {
|
||||
|
||||
if (EnumSet.of(RestOperationTypeEnum.CREATE, RestOperationTypeEnum.UPDATE).contains(getRestOperationType())) {
|
||||
allowPrefer = true;
|
||||
}
|
||||
|
||||
|
||||
if (resource != null && allowPrefer) {
|
||||
String prefer = theRequest.getHeader(Constants.HEADER_PREFER);
|
||||
|
@ -230,8 +202,16 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
outcome = resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, outcome);
|
||||
if (!continueProcessing) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return theRequest.getResponse().returnResponse(ParseAction.create(outcome), operationStatus, allowPrefer, response, getResourceName());
|
||||
}
|
||||
|
||||
|
@ -241,8 +221,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
protected abstract Set<RequestTypeEnum> provideAllowableRequestTypes();
|
||||
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest)
|
||||
throws IOException {
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest) throws IOException {
|
||||
theResponse.setStatus(theE.getStatusCode());
|
||||
|
||||
theServer.addHeadersToResponse(theResponse);
|
||||
|
|
|
@ -94,41 +94,38 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
|
||||
throws InternalErrorException {
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding)
|
||||
throws InternalErrorException, InvalidRequestException {
|
||||
switch (myMode) {
|
||||
case BODY:
|
||||
try {
|
||||
return IOUtils.toString(createRequestReader(theRequest));
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Shouldn't happen since we're reading from a byte array
|
||||
throw new InternalErrorException("Failed to load request");
|
||||
}
|
||||
case ENCODING:
|
||||
return RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
case RESOURCE:
|
||||
default:
|
||||
return parseResourceFromRequest(theRequest, theMethodBinding, myResourceType);
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
switch (myMode) {
|
||||
case BODY:
|
||||
try {
|
||||
return IOUtils.toString(createRequestReader(theRequest));
|
||||
} catch (IOException e) {
|
||||
// Shouldn't happen since we're reading from a byte array
|
||||
throw new InternalErrorException("Failed to load request");
|
||||
}
|
||||
// }
|
||||
case ENCODING:
|
||||
return RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
case RESOURCE:
|
||||
default:
|
||||
return parseResourceFromRequest(theRequest, theMethodBinding, myResourceType);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
public static Reader createRequestReader(RequestDetails theRequest, Charset charset) {
|
||||
Reader requestReader = new InputStreamReader(new ByteArrayInputStream(theRequest.loadRequestContents()), charset);
|
||||
return requestReader;
|
||||
}
|
||||
|
||||
public static Reader createRequestReader(RequestDetails theRequest) throws IOException {
|
||||
public static Reader createRequestReader(RequestDetails theRequest) {
|
||||
return createRequestReader(theRequest, determineRequestCharset(theRequest));
|
||||
}
|
||||
}
|
||||
|
||||
public static Charset determineRequestCharset(RequestDetails theRequest) {
|
||||
String ct = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
@ -142,11 +139,10 @@ public class ResourceParameter implements IParameter {
|
|||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
return charset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding,
|
||||
Class<T> theResourceType) {
|
||||
public static <T extends IBaseResource> T loadResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding, Class<T> theResourceType) {
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
|
||||
final Charset charset = determineRequestCharset(theRequest);
|
||||
|
@ -170,7 +166,7 @@ public class ResourceParameter implements IParameter {
|
|||
String body;
|
||||
try {
|
||||
body = IOUtils.toString(requestReader);
|
||||
} catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
// This shouldn't happen since we're reading from a byte array..
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
@ -210,8 +206,8 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static IBaseResource parseResourceFromRequest(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||
IBaseResource retVal;
|
||||
if (IBaseBinary.class.isAssignableFrom(theResourceType)) {
|
||||
|
@ -226,7 +222,7 @@ public class ResourceParameter implements IParameter {
|
|||
retVal = loadResourceFromRequest(theRequest, theMethodBinding, theResourceType);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
BODY, ENCODING, RESOURCE
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -108,13 +106,7 @@ public class TransactionParameter implements IParameter {
|
|||
IParser parser = encoding.newParser(theRequest.getServer().getFhirContext());
|
||||
|
||||
Reader reader;
|
||||
try {
|
||||
reader = ResourceParameter.createRequestReader(theRequest);
|
||||
}
|
||||
catch (IOException e) {
|
||||
ourLog.error("Could not load request resource", e);
|
||||
throw new InvalidRequestException(String.format("Could not load request resource: %s", e.getMessage()));
|
||||
}
|
||||
reader = ResourceParameter.createRequestReader(theRequest);
|
||||
|
||||
switch (myParamStyle) {
|
||||
case DSTU1_BUNDLE: {
|
||||
|
|
|
@ -35,17 +35,18 @@ import ca.uhn.fhir.rest.method.ParseAction;
|
|||
|
||||
public interface IRestfulResponse {
|
||||
|
||||
Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set<SummaryEnum> summaryMode, int operationStatus, boolean respondGzip, boolean addContentLocationHeader)
|
||||
throws IOException;
|
||||
Object streamResponseAsBundle(Bundle bundle, Set<SummaryEnum> summaryMode, boolean respondGzip, boolean requestIsBrowser)
|
||||
throws IOException;
|
||||
Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set<SummaryEnum> summaryMode, int operationStatus, boolean respondGzip, boolean addContentLocationHeader) throws IOException;
|
||||
|
||||
Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException;
|
||||
|
||||
Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip) throws UnsupportedEncodingException, IOException;
|
||||
Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException;
|
||||
|
||||
void addHeader(String headerKey, String headerValue);
|
||||
Object streamResponseAsBundle(Bundle bundle, Set<SummaryEnum> summaryMode, boolean respondGzip, boolean requestIsBrowser) throws IOException;
|
||||
|
||||
Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException;
|
||||
|
||||
Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip) throws UnsupportedEncodingException, IOException;
|
||||
|
||||
Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException;
|
||||
|
||||
void addHeader(String headerKey, String headerValue);
|
||||
|
||||
Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException;
|
||||
|
||||
Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.text.StrLookup;
|
||||
import org.apache.commons.lang3.text.StrSubstitutor;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
/**
|
||||
* This interceptor intercepts each incoming request and if it contains a FHIR resource, validates that resource. The
|
||||
* interceptor may be configured to run any validator modules, and will then add headers to the response or fail the
|
||||
* request with an {@link UnprocessableEntityException HTTP 422 Unprocessable Entity}.
|
||||
*/
|
||||
abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||
|
||||
/**
|
||||
* Default value:<br/>
|
||||
* <code>
|
||||
* ${row}:${col} ${severity} ${message} (${location})
|
||||
* </code>
|
||||
*/
|
||||
public static final String DEFAULT_RESPONSE_HEADER_VALUE = "${row}:${col} ${severity} ${message} (${location})";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseValidatingInterceptor.class);
|
||||
|
||||
private Integer myAddResponseHeaderOnSeverity = ResultSeverityEnum.INFORMATION.ordinal();
|
||||
private Integer myFailOnSeverity = ResultSeverityEnum.ERROR.ordinal();
|
||||
private String myResponseHeaderName = provideDefaultResponseHeaderName();
|
||||
private String myResponseHeaderValue = DEFAULT_RESPONSE_HEADER_VALUE;
|
||||
private String myResponseHeaderValueNoIssues = null;
|
||||
|
||||
private List<IValidatorModule> myValidatorModules;
|
||||
|
||||
private void addResponseHeader(RequestDetails theRequestDetails, SingleValidationMessage theNext) {
|
||||
// Perform any string substitutions from the message format
|
||||
StrLookup<?> lookup = new MyLookup(theNext);
|
||||
StrSubstitutor subs = new StrSubstitutor(lookup, "${", "}", '\\');
|
||||
|
||||
// Log the header
|
||||
String headerValue = subs.replace(myResponseHeaderValue);
|
||||
ourLog.trace("Adding header to response: {}", headerValue);
|
||||
|
||||
theRequestDetails.getResponse().addHeader(myResponseHeaderName, headerValue);
|
||||
}
|
||||
|
||||
public BaseValidatingInterceptor addValidatorModule(IValidatorModule theModule) {
|
||||
Validate.notNull(theModule, "theModule must not be null");
|
||||
if (getValidatorModules() == null) {
|
||||
setValidatorModules(new ArrayList<IValidatorModule>());
|
||||
}
|
||||
getValidatorModules().add(theModule);
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract ValidationResult doValidate(FhirValidator theValidator, T theRequest);
|
||||
|
||||
/**
|
||||
* Fail the request by throwing an {@link UnprocessableEntityException} as a result of a validation failure.
|
||||
* Subclasses may change this behaviour by providing alternate behaviour.
|
||||
*/
|
||||
protected void fail(RequestDetails theRequestDetails, ValidationResult theValidationResult) {
|
||||
throw new UnprocessableEntityException(theRequestDetails.getServer().getFhirContext(), theValidationResult.toOperationOutcome());
|
||||
}
|
||||
|
||||
public List<IValidatorModule> getValidatorModules() {
|
||||
return myValidatorModules;
|
||||
}
|
||||
|
||||
abstract String provideDefaultResponseHeaderName();
|
||||
|
||||
/**
|
||||
* Sets the minimum severity at which an issue detected by the validator will result in a header being added to the
|
||||
* response. Default is {@link ResultSeverityEnum#INFORMATION}. Set to <code>null</code> to disable this behaviour.
|
||||
*
|
||||
* @see #setResponseHeaderName(String)
|
||||
* @see #setResponseHeaderValue(String)
|
||||
*/
|
||||
public void setAddResponseHeaderOnSeverity(ResultSeverityEnum theSeverity) {
|
||||
myAddResponseHeaderOnSeverity = theSeverity != null ? theSeverity.ordinal() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum severity at which an issue detected by the validator will fail/reject the request. Default is
|
||||
* {@link ResultSeverityEnum#ERROR}. Set to <code>null</code> to disable this behaviour.
|
||||
*/
|
||||
public void setFailOnSeverity(ResultSeverityEnum theSeverity) {
|
||||
myFailOnSeverity = theSeverity != null ? theSeverity.ordinal() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the response header to add validation failures to
|
||||
*
|
||||
* @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
|
||||
*/
|
||||
protected void setResponseHeaderName(String theResponseHeaderName) {
|
||||
Validate.notBlank(theResponseHeaderName, "theResponseHeaderName must not be blank or null");
|
||||
myResponseHeaderName = theResponseHeaderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value to add to the response header with the name specified by {@link #setResponseHeaderName(String)}
|
||||
* when validation produces a message of severity equal to or greater than
|
||||
* {@link #setAddResponseHeaderOnSeverity(ResultSeverityEnum)}
|
||||
* <p>
|
||||
* This field allows the following substitutions:
|
||||
* </p>
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>Name</td>
|
||||
* <td>Value</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${line}</td>
|
||||
* <td>The line in the request</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${col}</td>
|
||||
* <td>The column in the request</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${location}</td>
|
||||
* <td>The location in the payload as a string (typically this will be a path)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${severity}</td>
|
||||
* <td>The severity of the issue</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${message}</td>
|
||||
* <td>The validation message</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* @see #DEFAULT_RESPONSE_HEADER_VALUE
|
||||
* @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
|
||||
*/
|
||||
public void setResponseHeaderValue(String theResponseHeaderValue) {
|
||||
Validate.notBlank(theResponseHeaderValue, "theResponseHeaderValue must not be blank or null");
|
||||
myResponseHeaderValue = theResponseHeaderValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the header value to add when no issues are found at or exceeding the
|
||||
* threshold specified by {@link #setAddResponseHeaderOnSeverity(ResultSeverityEnum)}
|
||||
*/
|
||||
public void setResponseHeaderValueNoIssues(String theResponseHeaderValueNoIssues) {
|
||||
myResponseHeaderValueNoIssues = theResponseHeaderValueNoIssues;
|
||||
}
|
||||
|
||||
public void setValidatorModules(List<IValidatorModule> theValidatorModules) {
|
||||
myValidatorModules = theValidatorModules;
|
||||
}
|
||||
|
||||
protected void validate(T theRequest, RequestDetails theRequestDetails) {
|
||||
FhirValidator validator = theRequestDetails.getServer().getFhirContext().newValidator();
|
||||
if (myValidatorModules != null) {
|
||||
for (IValidatorModule next : myValidatorModules) {
|
||||
validator.registerValidatorModule(next);
|
||||
}
|
||||
}
|
||||
|
||||
ValidationResult validationResult = doValidate(validator, theRequest);
|
||||
|
||||
if (myAddResponseHeaderOnSeverity != null) {
|
||||
boolean found = false;
|
||||
for (SingleValidationMessage next : validationResult.getMessages()) {
|
||||
if (next.getSeverity().ordinal() >= myAddResponseHeaderOnSeverity) {
|
||||
addResponseHeader(theRequestDetails, next);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (isNotBlank(myResponseHeaderValueNoIssues)) {
|
||||
theRequestDetails.getResponse().addHeader(myResponseHeaderName, myResponseHeaderValueNoIssues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myFailOnSeverity != null) {
|
||||
for (SingleValidationMessage next : validationResult.getMessages()) {
|
||||
if (next.getSeverity().ordinal() >= myFailOnSeverity) {
|
||||
fail(theRequestDetails, validationResult);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyLookup extends StrLookup<String> {
|
||||
|
||||
private SingleValidationMessage myMessage;
|
||||
|
||||
public MyLookup(SingleValidationMessage theMessage) {
|
||||
myMessage = theMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String lookup(String theKey) {
|
||||
if ("line".equals(theKey)) {
|
||||
return toString(myMessage.getLocationLine());
|
||||
}
|
||||
if ("col".equals(theKey)) {
|
||||
return toString(myMessage.getLocationCol());
|
||||
}
|
||||
if ("message".equals(theKey)) {
|
||||
return toString(myMessage.getMessage());
|
||||
}
|
||||
if ("location".equals(theKey)) {
|
||||
return toString(myMessage.getLocationString());
|
||||
}
|
||||
if ("severity".equals(theKey)) {
|
||||
return myMessage.getSeverity() != null ? myMessage.getSeverity().name() : null;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String toString(Object theInt) {
|
||||
return theInt != null ? theInt.toString() : "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
|
@ -41,41 +42,50 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
|
||||
/**
|
||||
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish to use {@link InterceptorAdapter} in order to not need to implement every method.
|
||||
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish to use
|
||||
* {@link InterceptorAdapter} in order to not need to implement every method.
|
||||
* <p>
|
||||
* <b>See:</b> See the <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_server_interceptor.html">server interceptor documentation</a> for more information on how to use this class.
|
||||
* <b>See:</b> See the <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_server_interceptor.html">server
|
||||
* interceptor documentation</a> for more information on how to use this class.
|
||||
* </p>
|
||||
*/
|
||||
public interface IServerInterceptor {
|
||||
|
||||
/**
|
||||
* This method is called upon any exception being thrown within the server's request processing code. This includes any exceptions thrown within resource provider methods (e.g. {@link Search} and
|
||||
* {@link Read} methods) as well as any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}s thrown.
|
||||
* This method is called upon any exception being thrown within the server's request processing code. This includes
|
||||
* any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
|
||||
* any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}s
|
||||
* thrown.
|
||||
* <p>
|
||||
* Implementations of this method may choose to ignore/log/count/etc exceptions, and return <code>true</code>. In this case, processing will continue, and the server will automatically generate an
|
||||
* {@link BaseOperationOutcome OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they should return <code>false</code>, to indicate that
|
||||
* they have handled the request and processing should stop.
|
||||
* Implementations of this method may choose to ignore/log/count/etc exceptions, and return <code>true</code>. In
|
||||
* this case, processing will continue, and the server will automatically generate an {@link BaseOperationOutcome
|
||||
* OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they
|
||||
* should return <code>false</code>, to indicate that they have handled the request and processing should stop.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link javax.servlet.http.HttpServletRequest servlet request}. Note that the bean properties are not all guaranteed to be populated, depending
|
||||
* on how early during processing the exception occurred.
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link javax.servlet.http.HttpServletRequest servlet request}. Note that the bean
|
||||
* properties are not all guaranteed to be populated, depending on how early during processing the
|
||||
* exception occurred.
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link javax.servlet.http.HttpServletResponse#getWriter()}) but in that case it is important to
|
||||
* return <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link javax.servlet.http.HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws ServletException
|
||||
* If this exception is thrown, it will be re-thrown up to the container for handling.
|
||||
* @throws IOException
|
||||
* If this exception is thrown, it will be re-thrown up to the container for handling.
|
||||
*/
|
||||
boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws ServletException, IOException;
|
||||
boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws ServletException, IOException;
|
||||
|
||||
/**
|
||||
* This method is called just before the actual implementing server method is invoked.
|
||||
|
@ -84,18 +94,22 @@ public interface IServerInterceptor {
|
|||
* </p>
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException;
|
||||
|
||||
|
@ -107,14 +121,14 @@ public interface IServerInterceptor {
|
|||
* @param theOperation
|
||||
* The type of operation that the FHIR server has determined that the client is trying to invoke
|
||||
* @param theProcessedRequest
|
||||
* An object which will be populated with the details which were extracted from the raw request by the server,
|
||||
* e.g. the FHIR operation type and the parsed resource body (if any).
|
||||
* An object which will be populated with the details which were extracted from the raw request by the
|
||||
* server, e.g. the FHIR operation type and the parsed resource body (if any).
|
||||
*/
|
||||
void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theProcessedRequest);
|
||||
|
||||
/**
|
||||
* This method is called before any other processing takes place for each incoming request. It may be used to provide alternate handling for some requests, or to screen requests before they are
|
||||
* handled, etc.
|
||||
* This method is called before any other processing takes place for each incoming request. It may be used to provide
|
||||
* alternate handling for some requests, or to screen requests before they are handled, etc.
|
||||
* <p>
|
||||
* Note that any exceptions thrown by this method will not be trapped by HAPI (they will be passed up to the server)
|
||||
* </p>
|
||||
|
@ -122,15 +136,19 @@ public interface IServerInterceptor {
|
|||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
*/
|
||||
boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
|
@ -139,159 +157,198 @@ public interface IServerInterceptor {
|
|||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequest, Bundle bundle);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequest, Bundle bundle);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject);
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>false</code> to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject);
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theServletRequest
|
||||
* The incoming request
|
||||
* @param theServletResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||
* to indicate that the server itself should not also provide a response.
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the resource type and logical ID (if any) and other FHIR-specific aspects of the
|
||||
* request which have been pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
|
||||
* client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject);
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||
* response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the {@link HttpServletRequest servlet request}.
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
|
||||
* will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||
*/
|
||||
boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject);
|
||||
|
||||
/**
|
||||
* This method is called upon any exception being thrown within the server's request processing code. This includes any exceptions thrown within resource provider methods (e.g. {@link Search} and
|
||||
* {@link Read} methods) as well as any runtime exceptions thrown by the server itself. This method is invoked for each interceptor (until one of them returns a non-<code>null</code> response or
|
||||
* the end of the list is reached), after which {@link #handleException(RequestDetails, BaseServerResponseException, HttpServletRequest, HttpServletResponse)} is called for each interceptor.
|
||||
* This method is called upon any exception being thrown within the server's request processing code. This includes
|
||||
* any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
|
||||
* any runtime exceptions thrown by the server itself. This method is invoked for each interceptor (until one of them
|
||||
* returns a non-<code>null</code> response or the end of the list is reached), after which
|
||||
* {@link #handleException(RequestDetails, BaseServerResponseException, HttpServletRequest, HttpServletResponse)} is
|
||||
* called for each interceptor.
|
||||
* <p>
|
||||
* This may be used to add an OperationOutcome to a response, or to convert between exception types for any reason.
|
||||
* </p>
|
||||
* <p>
|
||||
* Implementations of this method may choose to ignore/log/count/etc exceptions, and return <code>null</code>. In this case, processing will continue, and the server will automatically generate an
|
||||
* {@link BaseOperationOutcome OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they should return a non-<code>null</code>, to indicate
|
||||
* that they have handled the request and processing should stop.
|
||||
* Implementations of this method may choose to ignore/log/count/etc exceptions, and return <code>null</code>. In
|
||||
* this case, processing will continue, and the server will automatically generate an {@link BaseOperationOutcome
|
||||
* OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they
|
||||
* should return a non-<code>null</code>, to indicate that they have handled the request and processing should stop.
|
||||
* </p>
|
||||
*
|
||||
* @return Returns the new exception to use for processing, or <code>null</code> if this interceptor is not trying to modify the exception. For example, if this interceptor has nothing to do with
|
||||
* exception processing, it should always return <code>null</code>. If this interceptor adds an OperationOutcome to the exception, it should return an exception.
|
||||
* @return Returns the new exception to use for processing, or <code>null</code> if this interceptor is not trying to
|
||||
* modify the exception. For example, if this interceptor has nothing to do with exception processing, it
|
||||
* should always return <code>null</code>. If this interceptor adds an OperationOutcome to the exception, it
|
||||
* should return an exception.
|
||||
*/
|
||||
BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException;
|
||||
|
||||
|
@ -300,19 +357,26 @@ public interface IServerInterceptor {
|
|||
private boolean myLocked = false;
|
||||
private IBaseResource myResource;
|
||||
private final String myResourceType;
|
||||
private final FhirContext myContext;
|
||||
|
||||
public ActionRequestDetails(IIdType theId, String theResourceType) {
|
||||
public ActionRequestDetails(IIdType theId, String theResourceType, FhirContext theContext) {
|
||||
myId = theId;
|
||||
myResourceType = theResourceType;
|
||||
myContext = theContext;
|
||||
}
|
||||
|
||||
public ActionRequestDetails(RequestDetails theRequestDetails) {
|
||||
myId = theRequestDetails.getId();
|
||||
myResourceType = theRequestDetails.getResourceName();
|
||||
myContext = theRequestDetails.getServer().getFhirContext();
|
||||
}
|
||||
|
||||
public ActionRequestDetails(IIdType theId, String theResourceType, IBaseResource theResource) {
|
||||
this(theId, theResourceType);
|
||||
public FhirContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
public ActionRequestDetails(IIdType theId, String theResourceType, IBaseResource theResource, FhirContext theContext) {
|
||||
this(theId, theResourceType, theContext);
|
||||
myResource = theResource;
|
||||
}
|
||||
|
||||
|
@ -324,10 +388,12 @@ public interface IServerInterceptor {
|
|||
}
|
||||
|
||||
/**
|
||||
* For requests where a resource is passed from the client to the server (e.g. create, update, etc.) this method will return the resource which was provided by the client. Otherwise, this method
|
||||
* will return <code>null</code>.
|
||||
* For requests where a resource is passed from the client to the server (e.g. create, update, etc.) this method
|
||||
* will return the resource which was provided by the client. Otherwise, this method will return <code>null</code>
|
||||
* .
|
||||
* <p>
|
||||
* Note that this method is currently only populated if the handling method has a parameter annotated with the {@link ResourceParam} annotation.
|
||||
* Note that this method is currently only populated if the handling method has a parameter annotated with the
|
||||
* {@link ResourceParam} annotation.
|
||||
* </p>
|
||||
*/
|
||||
public IBaseResource getResource() {
|
||||
|
@ -335,7 +401,8 @@ public interface IServerInterceptor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the resource type this request pertains to, or <code>null</code> if this request is not type specific (e.g. server-history)
|
||||
* Returns the resource type this request pertains to, or <code>null</code> if this request is not type specific
|
||||
* (e.g. server-history)
|
||||
*/
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
/**
|
||||
* This interceptor intercepts each incoming request and if it contains a FHIR resource, validates that resource. The
|
||||
* interceptor may be configured to run any validator modules, and will then add headers to the response or fail the
|
||||
* request with an {@link UnprocessableEntityException HTTP 422 Unprocessable Entity}.
|
||||
*/
|
||||
public class RequestValidatingInterceptor extends BaseValidatingInterceptor<String> {
|
||||
|
||||
/**
|
||||
* X-HAPI-Request-Validation
|
||||
*/
|
||||
public static final String DEFAULT_RESPONSE_HEADER_NAME = "X-HAPI-Request-Validation";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestValidatingInterceptor.class);
|
||||
|
||||
@Override
|
||||
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncodingNoDefault(theRequestDetails);
|
||||
if (encoding == null) {
|
||||
ourLog.trace("Incoming request does not appear to be FHIR, not going to validate");
|
||||
return true;
|
||||
}
|
||||
|
||||
Charset charset = ResourceParameter.determineRequestCharset(theRequestDetails);
|
||||
String requestText = new String(theRequestDetails.loadRequestContents(), charset);
|
||||
validate(requestText, theRequestDetails);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the response header to add validation failures to
|
||||
*
|
||||
* @see #DEFAULT_RESPONSE_HEADER_NAME
|
||||
* @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
|
||||
*/
|
||||
@Override
|
||||
public void setResponseHeaderName(String theResponseHeaderName) {
|
||||
super.setResponseHeaderName(theResponseHeaderName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
String provideDefaultResponseHeaderName() {
|
||||
return DEFAULT_RESPONSE_HEADER_NAME;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
ValidationResult doValidate(FhirValidator theValidator, String theRequest) {
|
||||
return theValidator.validateWithResult(theRequest);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -29,49 +31,54 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
/**
|
||||
* Not yet complete!
|
||||
*
|
||||
* TODO: complete this
|
||||
* This interceptor intercepts each outgoing response and if it contains a FHIR resource, validates that resource. The
|
||||
* interceptor may be configured to run any validator modules, and will then add headers to the response or fail the
|
||||
* request with an {@link UnprocessableEntityException HTTP 422 Unprocessable Entity}.
|
||||
*/
|
||||
class ResponseValidatingInterceptor extends InterceptorAdapter {
|
||||
public class ResponseValidatingInterceptor extends BaseValidatingInterceptor<IBaseResource> {
|
||||
|
||||
private FhirValidator myValidator;
|
||||
|
||||
/**
|
||||
* Returns the validator used by this interceptor
|
||||
* X-HAPI-Request-Validation
|
||||
*/
|
||||
public FhirValidator getValidator() {
|
||||
return myValidator;
|
||||
public static final String DEFAULT_RESPONSE_HEADER_NAME = "X-HAPI-Response-Validation";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptor.class);
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
|
||||
validate(theResponseObject, theRequestDetails);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the validator instance to use. Must not be null.
|
||||
* Sets the name of the response header to add validation failures to
|
||||
*
|
||||
* @see #DEFAULT_RESPONSE_HEADER_NAME
|
||||
* @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
|
||||
*/
|
||||
public void setValidator(FhirValidator theValidator) {
|
||||
Validate.notNull(theValidator, "Validator must not be null");
|
||||
myValidator = theValidator;
|
||||
@Override
|
||||
public void setResponseHeaderName(String theResponseHeaderName) {
|
||||
super.setResponseHeaderName(theResponseHeaderName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
String provideDefaultResponseHeaderName() {
|
||||
return DEFAULT_RESPONSE_HEADER_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
ValidationResult doValidate(FhirValidator theValidator, IBaseResource theRequest) {
|
||||
return theValidator.validateWithResult(theRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -38,60 +38,60 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.RestfulResponse;
|
||||
|
||||
public class ServletRestfulResponse extends RestfulResponse<ServletRequestDetails> {
|
||||
|
||||
public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
|
||||
super(servletRequestDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException {
|
||||
addHeaders();
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
theHttpResponse.setStatus(stausCode);
|
||||
theHttpResponse.setContentType(contentType);
|
||||
if (bin.getContent() == null || bin.getContent().length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
theHttpResponse.setContentLength(bin.getContent().length);
|
||||
ServletOutputStream oos = theHttpResponse.getOutputStream();
|
||||
oos.write(bin.getContent());
|
||||
oos.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
addHeaders();
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
theHttpResponse.setCharacterEncoding(charset);
|
||||
theHttpResponse.setStatus(statusCode);
|
||||
theHttpResponse.setContentType(contentType);
|
||||
public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
|
||||
super(servletRequestDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException {
|
||||
addHeaders();
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
theHttpResponse.setStatus(stausCode);
|
||||
theHttpResponse.setContentType(contentType);
|
||||
if (bin.getContent() == null || bin.getContent().length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
theHttpResponse.setContentLength(bin.getContent().length);
|
||||
ServletOutputStream oos = theHttpResponse.getOutputStream();
|
||||
oos.write(bin.getContent());
|
||||
oos.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
addHeaders();
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
theHttpResponse.setCharacterEncoding(charset);
|
||||
theHttpResponse.setStatus(statusCode);
|
||||
theHttpResponse.setContentType(contentType);
|
||||
if (theRespondGzip) {
|
||||
theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
|
||||
return new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), Constants.CHARSET_NAME_UTF8);
|
||||
} else {
|
||||
return theHttpResponse.getWriter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addHeaders() {
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
getRequestDetails().getServer().addHeadersToResponse(theHttpResponse);
|
||||
for (Entry<String, String> header : getHeaders().entrySet()) {
|
||||
theHttpResponse.setHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void addHeaders() {
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
getRequestDetails().getServer().addHeadersToResponse(theHttpResponse);
|
||||
for (Entry<String, String> header : getHeaders().entrySet()) {
|
||||
theHttpResponse.setHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException {
|
||||
writer.close();
|
||||
return null;
|
||||
}
|
||||
writer.close();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response,
|
||||
String resourceName) throws IOException {
|
||||
return getRequestDetails().getServer().returnResponse(getRequestDetails(), outcome, operationStatus, allowPrefer, response, resourceName);
|
||||
}
|
||||
@Override
|
||||
public Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException {
|
||||
addHeaders();
|
||||
return getRequestDetails().getServer().returnResponse(getRequestDetails(), outcome, operationStatus, allowPrefer, response, resourceName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
import org.hl7.fhir.dstu21.hapi.validation.DefaultProfileValidationSupport;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirQuestionnaireResponseValidator;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.IValidationSupport;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.dstu21.validation.IResourceValidator.BestPracticeWarningLevel;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
|
@ -21,8 +28,11 @@ package ca.uhn.fhir.jpa.config;
|
|||
*/
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
|
@ -30,6 +40,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.jpa.dao.FhirSearchDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.ISearchDao;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
|
@ -48,22 +59,48 @@ public class BaseDstu21Config extends BaseConfig {
|
|||
}
|
||||
|
||||
@Bean(name = "mySystemProviderDstu21")
|
||||
public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 systemProviderDstu2() {
|
||||
public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 systemProviderDstu21() {
|
||||
ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 retVal = new ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21();
|
||||
retVal.setDao(systemDaoDstu21());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean(name = "myJpaValidationSupportDstu21", autowire = Autowire.BY_NAME)
|
||||
public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 jpaValidationSupportDstu2() {
|
||||
public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 jpaValidationSupportDstu21() {
|
||||
ca.uhn.fhir.jpa.dao.JpaValidationSupportDstu21 retVal = new ca.uhn.fhir.jpa.dao.JpaValidationSupportDstu21();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Qualifier("myJpaValidationSupportDstu21")
|
||||
private IValidationSupport myJpaValidationSupportDstu21;
|
||||
|
||||
@Bean(autowire = Autowire.BY_TYPE)
|
||||
public ISearchDao searchDao() {
|
||||
public ISearchDao searchDaoDstu21() {
|
||||
FhirSearchDao searchDao = new FhirSearchDao();
|
||||
return searchDao;
|
||||
}
|
||||
|
||||
@Bean(name="myInstanceValidatorDstu21")
|
||||
@Lazy
|
||||
public IValidatorModule instanceValidatorDstu21() {
|
||||
FhirInstanceValidator val = new FhirInstanceValidator();
|
||||
val.setBestPracticeWarningLevel(BestPracticeWarningLevel.Warning);
|
||||
val.setValidationSupport(validationSupportChainDstu21());
|
||||
return val;
|
||||
}
|
||||
|
||||
@Bean(name="myQuestionnaireResponseValidatorDstu21")
|
||||
@Lazy
|
||||
public IValidatorModule questionnaireResponseValidatorDstu21() {
|
||||
FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator();
|
||||
module.setValidationSupport(validationSupportChainDstu21());
|
||||
return module;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IValidationSupport validationSupportChainDstu21() {
|
||||
return new ValidationSupportChain(new DefaultProfileValidationSupport(), myJpaValidationSupportDstu21);
|
||||
// return new ValidationSupportChain();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -154,26 +154,26 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
if (theResource.getIdElement().isIdPartValidLong()) {
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getIdElement().getIdPart());
|
||||
throw new InvalidRequestException(message, createErrorOperationOutcome(message));
|
||||
throw new InvalidRequestException(message, createErrorOperationOutcome(message, "processing"));
|
||||
}
|
||||
} else {
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getIdElement().getIdPart());
|
||||
throw new InvalidRequestException(message, createErrorOperationOutcome(message));
|
||||
throw new InvalidRequestException(message, createErrorOperationOutcome(message, "processing"));
|
||||
}
|
||||
}
|
||||
|
||||
return doCreate(theResource, theIfNoneExist, thePerformIndexing, new Date());
|
||||
}
|
||||
|
||||
public IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
|
||||
return createOperationOutcome(OO_SEVERITY_ERROR, theMessage);
|
||||
public IBaseOperationOutcome createErrorOperationOutcome(String theMessage, String theCode) {
|
||||
return createOperationOutcome(OO_SEVERITY_ERROR, theMessage, theCode);
|
||||
}
|
||||
|
||||
public IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
|
||||
return createOperationOutcome(OO_SEVERITY_INFO, theMessage);
|
||||
return createOperationOutcome(OO_SEVERITY_INFO, theMessage, "informational");
|
||||
}
|
||||
|
||||
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage);
|
||||
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode);
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome delete(IIdType theId) {
|
||||
|
@ -201,7 +201,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
||||
|
||||
Date updateTime = new Date();
|
||||
|
@ -251,7 +251,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
// Notify interceptors
|
||||
IdDt idToDelete = entity.getIdDt();
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
||||
|
||||
// Perform delete
|
||||
|
@ -308,7 +308,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
||||
|
||||
// Perform actual DB update
|
||||
|
@ -333,7 +333,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public TagList getAllResourceTags() {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -356,7 +356,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public TagList getTags(IIdType theResourceId) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -368,7 +368,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public IBundleProvider history(Date theSince) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -380,7 +380,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public IBundleProvider history(final IIdType theId, final Date theSince) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails);
|
||||
|
||||
final InstantDt end = createHistoryToTimestamp();
|
||||
|
@ -495,7 +495,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public IBundleProvider history(Long theId, Date theSince) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -507,7 +507,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -634,7 +634,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -675,7 +675,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
|
||||
|
||||
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)";
|
||||
|
@ -714,7 +714,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
|
||||
|
||||
Set<TagDefinition> tagDefs = new HashSet<TagDefinition>();
|
||||
|
@ -771,7 +771,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
validateResourceTypeAndThrowIllegalArgumentException(theId);
|
||||
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
|
||||
RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ;
|
||||
notifyInterceptors(operationType, requestDetails);
|
||||
|
||||
|
@ -863,7 +863,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -904,7 +904,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Override
|
||||
public IBundleProvider search(final SearchParameterMap theParams) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
||||
|
||||
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this);
|
||||
|
@ -1051,7 +1051,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails);
|
||||
|
||||
// Perform update
|
||||
|
|
|
@ -64,7 +64,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
@Override
|
||||
public void deleteAllTagsOnServer() {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
|
||||
|
||||
myEntityManager.createQuery("DELETE from ResourceTag t").executeUpdate();
|
||||
|
@ -122,7 +122,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
@Override
|
||||
public TagList getAllTags() {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -157,7 +157,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
@Override
|
||||
public IBundleProvider history(Date theSince) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
|
|
@ -60,7 +60,7 @@ public class FhirResourceDaoDstu1<T extends IResource> extends BaseHapiFhirResou
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
|
||||
oo.getIssueFirstRep().getDetailsElement().setValue(theMessage);
|
||||
|
|
|
@ -89,16 +89,17 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
|
||||
oo.getIssueFirstRep().getDiagnosticsElement().setValue(theMessage);
|
||||
oo.getIssueFirstRep().getCodeElement().setValue(theCode);
|
||||
return oo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
|
||||
|
||||
if (theMode == ValidationModeEnum.DELETE) {
|
||||
|
|
|
@ -26,13 +26,12 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.IValidationSupport;
|
||||
import org.hl7.fhir.dstu21.exceptions.FHIRException;
|
||||
import org.hl7.fhir.dstu21.model.IdType;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome.IssueSeverity;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.dstu21.validation.IResourceValidator.BestPracticeWarningLevel;
|
||||
import org.hl7.fhir.instance.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -63,11 +62,26 @@ import ca.uhn.fhir.validation.ValidationResult;
|
|||
|
||||
public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirResourceDao<T> {
|
||||
|
||||
@Autowired()
|
||||
@Qualifier("myJpaValidationSupportDstu21")
|
||||
private IValidationSupport myJpaValidationSupport;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu21.class);
|
||||
|
||||
@Autowired()
|
||||
@Qualifier("myInstanceValidatorDstu21")
|
||||
private IValidatorModule myInstanceValidator;
|
||||
|
||||
@Override
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
OperationOutcomeIssueComponent issue = oo.addIssue();
|
||||
issue.getSeverityElement().setValueAsString(theSeverity);
|
||||
issue.setDiagnostics(theMessage);
|
||||
try {
|
||||
issue.setCode(org.hl7.fhir.dstu21.model.OperationOutcome.IssueType.fromCode(theCode));
|
||||
} catch (FHIRException e) {
|
||||
ourLog.error("Unknown code: {}", theCode);
|
||||
}
|
||||
return oo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef) {
|
||||
List<Object> values;
|
||||
|
@ -86,18 +100,9 @@ public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirR
|
|||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
OperationOutcomeIssueComponent issue = oo.addIssue();
|
||||
issue.getSeverityElement().setValueAsString(theSeverity);
|
||||
issue.setDiagnostics(theMessage);
|
||||
return oo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
|
||||
|
||||
if (theMode == ValidationModeEnum.DELETE) {
|
||||
|
@ -111,7 +116,7 @@ public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirR
|
|||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
|
||||
|
||||
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setSeverity(IssueSeverity.INFORMATION).setDiagnostics("Ok to delete");
|
||||
return new MethodOutcome(new IdType(theId.getValue()), oo);
|
||||
|
@ -119,10 +124,7 @@ public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirR
|
|||
|
||||
FhirValidator validator = getContext().newValidator();
|
||||
|
||||
FhirInstanceValidator val = new FhirInstanceValidator();
|
||||
val.setBestPracticeWarningLevel(BestPracticeWarningLevel.Warning);
|
||||
// val.setValidationSupport(new ValidationSupportChain(new DefaultProfileValidationSupport(), myJpaValidationSupport));
|
||||
validator.registerValidatorModule(val);
|
||||
validator.registerValidatorModule(myInstanceValidator);
|
||||
|
||||
validator.registerValidatorModule(new IdChecker(theMode));
|
||||
|
||||
|
@ -151,6 +153,12 @@ public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirR
|
|||
myMode = theMode;
|
||||
}
|
||||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public void validateBundle(IValidationContext<Bundle> theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateResource(IValidationContext<IBaseResource> theCtx) {
|
||||
boolean hasId = theCtx.getResource().getIdElement().hasIdPart();
|
||||
|
@ -166,12 +174,6 @@ public class FhirResourceDaoDstu21<T extends IAnyResource> extends BaseHapiFhirR
|
|||
|
||||
}
|
||||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public void validateBundle(IValidationContext<Bundle> theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
|
|||
@Override
|
||||
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
|
||||
|
||||
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
|
||||
|
@ -77,7 +77,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
|
|||
@Override
|
||||
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
|
||||
|
||||
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);
|
||||
|
|
|
@ -68,7 +68,7 @@ public class FhirResourceDaoPatientDstu21 extends FhirResourceDaoDstu21<Patient>
|
|||
@Override
|
||||
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
|
||||
|
||||
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
|
||||
|
@ -77,7 +77,7 @@ public class FhirResourceDaoPatientDstu21 extends FhirResourceDaoDstu21<Patient>
|
|||
@Override
|
||||
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
|
||||
|
||||
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirQuestionnaireResponseValidator;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu21.model.Questionnaire;
|
||||
import org.hl7.fhir.dstu21.model.QuestionnaireResponse;
|
||||
|
@ -31,20 +30,24 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.IResourceLoader;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
public class FhirResourceDaoQuestionnaireResponseDstu21 extends FhirResourceDaoDstu21<QuestionnaireResponse> {
|
||||
|
||||
private Boolean myValidateResponses;
|
||||
|
||||
|
||||
@Autowired
|
||||
private IJpaValidationSupportDstu21 myValidationSupport;
|
||||
@Qualifier("myQuestionnaireResponseValidatorDstu21")
|
||||
private IValidatorModule myQuestionnaireResponseValidatorDstu21;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the bean
|
||||
|
@ -75,9 +78,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu21 extends FhirResourceDaoD
|
|||
val.setValidateAgainstStandardSchema(false);
|
||||
val.setValidateAgainstStandardSchematron(false);
|
||||
|
||||
FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator();
|
||||
module.setValidationSupport(myValidationSupport);
|
||||
val.registerValidatorModule(module);
|
||||
val.registerValidatorModule(myQuestionnaireResponseValidatorDstu21);
|
||||
|
||||
ValidationResult result = val.validateWithResult(getContext().newJsonParser().parseResource(getContext().newJsonParser().encodeResourceToString(qa)));
|
||||
if (!result.isSuccessful()) {
|
||||
|
|
|
@ -64,7 +64,7 @@ public class FhirSystemDaoDstu1 extends BaseHapiFhirSystemDao<List<IResource>, M
|
|||
ourLog.info("Beginning transaction with {} resources", theResources.size());
|
||||
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
|
|
@ -200,7 +200,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
@Override
|
||||
public MetaDt metaGetOperation() {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
|
||||
|
||||
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)";
|
||||
|
@ -259,7 +259,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
|
||||
|
||||
String actionName = "Transaction";
|
||||
|
|
|
@ -201,7 +201,7 @@ public class FhirSystemDaoDstu21 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
@Override
|
||||
public Meta metaGetOperation() {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
|
||||
|
||||
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)";
|
||||
|
@ -260,7 +260,7 @@ public class FhirSystemDaoDstu21 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest);
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext());
|
||||
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
|
||||
|
||||
String actionName = "Transaction";
|
||||
|
|
|
@ -74,6 +74,7 @@ import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
|||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
|
@ -297,9 +298,10 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
@Test
|
||||
public void testCreateOperationOutcomeError() {
|
||||
FhirResourceDaoDstu2<Bundle> dao = new FhirResourceDaoDstu2<Bundle>();
|
||||
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message");
|
||||
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message", "incomplete");
|
||||
assertEquals(IssueSeverityEnum.ERROR.getCode(), oo.getIssue().get(0).getSeverity());
|
||||
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals(IssueTypeEnum.INCOMPLETE_RESULTS, oo.getIssue().get(0).getCodeElement().getValueAsEnum());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -83,7 +83,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||
|
||||
//@formatter:off
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes= {TestDstu21Config.class /*, ca.uhn.fhir.jpa.config.WebsocketDstu21Config.class*/ })
|
||||
@ContextConfiguration(classes= {TestDstu21Config.class})
|
||||
//@formatter:on
|
||||
public abstract class BaseJpaDstu21Test extends BaseJpaTest {
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.hl7.fhir.dstu21.model.Meta;
|
|||
import org.hl7.fhir.dstu21.model.Observation;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome.IssueSeverity;
|
||||
import org.hl7.fhir.dstu21.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.dstu21.model.Organization;
|
||||
import org.hl7.fhir.dstu21.model.Patient;
|
||||
import org.hl7.fhir.dstu21.model.Period;
|
||||
|
@ -293,9 +294,10 @@ public class FhirResourceDaoDstu21Test extends BaseJpaDstu21Test {
|
|||
@Test
|
||||
public void testCreateOperationOutcomeError() {
|
||||
FhirResourceDaoDstu21<Bundle> dao = new FhirResourceDaoDstu21<Bundle>();
|
||||
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message");
|
||||
OperationOutcome oo = (OperationOutcome) dao.createErrorOperationOutcome("my message", "incomplete");
|
||||
assertEquals(IssueSeverity.ERROR.toCode(), oo.getIssue().get(0).getSeverity().toCode());
|
||||
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals(IssueType.INCOMPLETE, oo.getIssue().get(0).getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -304,6 +306,7 @@ public class FhirResourceDaoDstu21Test extends BaseJpaDstu21Test {
|
|||
OperationOutcome oo = (OperationOutcome) dao.createInfoOperationOutcome("my message");
|
||||
assertEquals(IssueSeverity.INFORMATION.toCode(), oo.getIssue().get(0).getSeverity().toCode());
|
||||
assertEquals("my message", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals(IssueType.INFORMATIONAL, oo.getIssue().get(0).getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.config.WebsocketDstu21Config;
|
||||
|
@ -32,7 +33,10 @@ import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
|||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhirtest.config.TestDstu21Config;
|
||||
import ca.uhn.fhirtest.config.TestDstu2Config;
|
||||
|
||||
|
@ -42,7 +46,7 @@ public class TestRestfulServer extends RestfulServer {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TestRestfulServer.class);
|
||||
|
||||
private AnnotationConfigApplicationContext myAppCtx;
|
||||
private AnnotationConfigWebApplicationContext myAppCtx;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
|
@ -72,7 +76,11 @@ public class TestRestfulServer extends RestfulServer {
|
|||
String baseUrlProperty;
|
||||
switch (fhirVersionParam.trim().toUpperCase()) {
|
||||
case "DSTU1": {
|
||||
myAppCtx = new AnnotationConfigApplicationContext(ca.uhn.fhirtest.config.TestDstu1Config.class);
|
||||
myAppCtx = new AnnotationConfigWebApplicationContext();
|
||||
myAppCtx.setServletConfig(getServletConfig());
|
||||
myAppCtx.setParent(parentAppCtx);
|
||||
myAppCtx.register(ca.uhn.fhirtest.config.TestDstu1Config.class);
|
||||
myAppCtx.refresh();
|
||||
setFhirContext(FhirContext.forDstu1());
|
||||
beans = myAppCtx.getBean("myResourceProvidersDstu1", List.class);
|
||||
systemProviderDstu1 = myAppCtx.getBean("mySystemProviderDstu1", JpaSystemProviderDstu1.class);
|
||||
|
@ -85,7 +93,8 @@ public class TestRestfulServer extends RestfulServer {
|
|||
break;
|
||||
}
|
||||
case "DSTU2": {
|
||||
myAppCtx = new AnnotationConfigApplicationContext();
|
||||
myAppCtx = new AnnotationConfigWebApplicationContext();
|
||||
myAppCtx.setServletConfig(getServletConfig());
|
||||
myAppCtx.setParent(parentAppCtx);
|
||||
myAppCtx.register(TestDstu2Config.class, WebsocketDstu2Config.class);
|
||||
myAppCtx.refresh();
|
||||
|
@ -101,7 +110,8 @@ public class TestRestfulServer extends RestfulServer {
|
|||
break;
|
||||
}
|
||||
case "DSTU21": {
|
||||
myAppCtx = new AnnotationConfigApplicationContext();
|
||||
myAppCtx = new AnnotationConfigWebApplicationContext();
|
||||
myAppCtx.setServletConfig(getServletConfig());
|
||||
myAppCtx.setParent(parentAppCtx);
|
||||
myAppCtx.register(TestDstu21Config.class, WebsocketDstu21Config.class);
|
||||
myAppCtx.refresh();
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.apache.commons.dbcp2.BasicDataSource;
|
|||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -23,6 +25,9 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu21;
|
|||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu21;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
@Configuration
|
||||
@Import(CommonConfig.class)
|
||||
|
@ -35,13 +40,13 @@ public class TestDstu21Config extends BaseJavaConfigDstu21 {
|
|||
@Value("${fhir.lucene.location.dstu21}")
|
||||
private String myFhirLuceneLocation;
|
||||
|
||||
/**
|
||||
* This lets the "@Value" fields reference properties from the properties file
|
||||
*/
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
@Autowired
|
||||
@Qualifier("myInstanceValidatorDstu21")
|
||||
private IValidatorModule myInstanceValidatorDstu21;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("myQuestionnaireResponseValidatorDstu21")
|
||||
private IValidatorModule myQuestionnaireResponseValidatorDstu21;
|
||||
|
||||
@Bean()
|
||||
public DaoConfig daoConfig() {
|
||||
|
@ -65,13 +70,6 @@ public class TestDstu21Config extends BaseJavaConfigDstu21 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Bean()
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager retVal = new JpaTransactionManager();
|
||||
retVal.setEntityManagerFactory(entityManagerFactory);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = new LocalContainerEntityManagerFactoryBean();
|
||||
|
@ -94,16 +92,54 @@ public class TestDstu21Config extends BaseJavaConfigDstu21 {
|
|||
extraProperties.put("hibernate.cache.use_second_level_cache", "false");
|
||||
extraProperties.put("hibernate.cache.use_structured_entries", "false");
|
||||
extraProperties.put("hibernate.cache.use_minimal_puts", "false");
|
||||
extraProperties.put("hibernate.search.default.directory_provider" ,"filesystem");
|
||||
extraProperties.put("hibernate.search.default.directory_provider", "filesystem");
|
||||
extraProperties.put("hibernate.search.default.indexBase", myFhirLuceneLocation);
|
||||
extraProperties.put("hibernate.search.lucene_version","LUCENE_CURRENT");
|
||||
extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT");
|
||||
return extraProperties;
|
||||
}
|
||||
|
||||
@Bean(autowire=Autowire.BY_TYPE)
|
||||
/**
|
||||
* Bean which validates incoming requests
|
||||
*/
|
||||
@Bean
|
||||
public IServerInterceptor requestValidatingInterceptor() {
|
||||
RequestValidatingInterceptor requestValidator = new RequestValidatingInterceptor();
|
||||
requestValidator.addValidatorModule(myInstanceValidatorDstu21);
|
||||
requestValidator.addValidatorModule(myQuestionnaireResponseValidatorDstu21);
|
||||
requestValidator.setResponseHeaderValueNoIssues("Validation did not detect any issues");
|
||||
return requestValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean which validates outgoing responses
|
||||
*/
|
||||
@Bean
|
||||
public IServerInterceptor responseValidatingInterceptor() {
|
||||
ResponseValidatingInterceptor responseValidator = new ResponseValidatingInterceptor();
|
||||
responseValidator.addValidatorModule(myInstanceValidatorDstu21);
|
||||
responseValidator.addValidatorModule(myQuestionnaireResponseValidatorDstu21);
|
||||
responseValidator.setResponseHeaderValueNoIssues("Validation did not detect any issues");
|
||||
responseValidator.setFailOnSeverity(null);
|
||||
return responseValidator;
|
||||
}
|
||||
|
||||
@Bean(autowire = Autowire.BY_TYPE)
|
||||
public IServerInterceptor subscriptionSecurityInterceptor() {
|
||||
return new SubscriptionsRequireManualActivationInterceptorDstu21();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Bean()
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager retVal = new JpaTransactionManager();
|
||||
retVal.setEntityManagerFactory(entityManagerFactory);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This lets the "@Value" fields reference properties from the properties file
|
||||
*/
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.validation.IValidationContext;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
public class FhirQuestionnaireResponseValidator extends BaseValidatorBridge {
|
||||
public class FhirQuestionnaireResponseValidator extends BaseValidatorBridge implements IValidatorModule {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirQuestionnaireResponseValidator.class);
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Class annotation used to indicate a class which is a "block"/"component" type. A block
|
||||
* is a nested group of fields within a resource definition and can contain other blocks as
|
||||
* well as data types.
|
||||
* <p>
|
||||
* An example of a block would be Patient.contact
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.TYPE})
|
||||
public @interface Block {
|
||||
|
||||
/**
|
||||
* @deprecated Do not use, will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
String name() default "";
|
||||
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - HL7.org DSTU2
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.hl7.fhir.dstu21.model.Enumeration;
|
||||
import org.hl7.fhir.dstu21.model.api.IBase;
|
||||
import org.hl7.fhir.dstu21.model.api.IBaseEnumFactory;
|
||||
|
||||
/**
|
||||
* Field annotation for fields within resource and datatype definitions, indicating
|
||||
* a child of that type.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.FIELD})
|
||||
public @interface Child {
|
||||
|
||||
/**
|
||||
* Constant value to supply for {@link #order()} when the order is defined
|
||||
* elsewhere
|
||||
*/
|
||||
int ORDER_UNKNOWN = -1;
|
||||
|
||||
/**
|
||||
* Constant value to supply for {@link #max()} to indicate '*' (no maximum)
|
||||
*/
|
||||
int MAX_UNLIMITED = -1;
|
||||
|
||||
/**
|
||||
* Constant value to supply for {@link #order()} to indicate that this child should replace the
|
||||
* entry in the superclass with the same name (and take its {@link Child#order() order} value
|
||||
* in the process). This is useful if you wish to redefine an existing field in a resource/type
|
||||
* definition in order to constrain/extend it.
|
||||
*/
|
||||
int REPLACE_PARENT = -2;
|
||||
|
||||
/**
|
||||
* The name of this field, as it will appear in serialized versions of the message
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* The order in which this field comes within its parent. The first field should have a
|
||||
* value of 0, the second a value of 1, etc.
|
||||
*/
|
||||
int order() default ORDER_UNKNOWN;
|
||||
|
||||
/**
|
||||
* The minimum number of repetitions allowed for this child
|
||||
*/
|
||||
int min() default 0;
|
||||
|
||||
/**
|
||||
* The maximum number of repetitions allowed for this child. Should be
|
||||
* set to {@link #MAX_UNLIMITED} if there is no limit to the number of
|
||||
* repetitions.
|
||||
*/
|
||||
int max() default 1;
|
||||
|
||||
/**
|
||||
* Lists the allowable types for this field, if the field supports multiple
|
||||
* types (otherwise does not need to be populated).
|
||||
* <p>
|
||||
* For example, if this field supports either DateTimeDt or BooleanDt types,
|
||||
* those two classes should be supplied here.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IBase>[] type() default {};
|
||||
|
||||
/**
|
||||
* For children which accept an {@link Enumeration} as the type, this
|
||||
* field indicates the type to use for the enum factory
|
||||
*/
|
||||
Class<? extends IBaseEnumFactory<?>> enumFactory() default NoEnumFactory.class;
|
||||
|
||||
/**
|
||||
* Is this element a modifier?
|
||||
*/
|
||||
boolean modifier() default false;
|
||||
|
||||
/**
|
||||
* Should this element be included in the summary view
|
||||
*/
|
||||
boolean summary() default false;
|
||||
|
||||
// Not implemented
|
||||
// /**
|
||||
// * This value is used when extending a built-in model class and defining a
|
||||
// * field to replace a field within the built-in class. For example, the {@link Patient}
|
||||
// * resource has a {@link Patient#getName() name} field, but if you wanted to extend Patient and
|
||||
// * provide your own implementation of {@link HumanNameDt} (most likely your own subclass of
|
||||
// * HumanNameDt which adds extensions of your choosing) you could do that using a replacement field.
|
||||
// */
|
||||
// String replaces() default "";
|
||||
|
||||
public static class NoEnumFactory implements IBaseEnumFactory<Enum<?>> {
|
||||
|
||||
private NoEnumFactory() {
|
||||
// non instantiable
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum<?> fromCode(String theCodeString) throws IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toCode(Enum<?> theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Structures - HL7.org DSTU2
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.hl7.fhir.dstu21.model.api.IBaseDatatype;
|
||||
|
||||
/**
|
||||
* Class annotation to note a class which defines a datatype
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.TYPE})
|
||||
public @interface DatatypeDef {
|
||||
|
||||
/**
|
||||
* The defined name of this datatype
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Set this to true (default is false) for any types that are
|
||||
* really only a specialization of another type. For example,
|
||||
* {@link BoundCodeDt} is really just a specific type of
|
||||
* {@link CodeDt} and not a separate datatype, so it should
|
||||
* have this set to true.
|
||||
*/
|
||||
boolean isSpecialization() default false;
|
||||
|
||||
/**
|
||||
* Indicates that this datatype is a profile of the given datatype, which
|
||||
* implies certain parsing/encoding rules (e.g. a choice element named
|
||||
* foo[x] which allows a Markdown value will still be encoded as
|
||||
* fooString because Markdown is a profile of string.
|
||||
*/
|
||||
Class<? extends IBaseDatatype> profileOf() default IBaseDatatype.class;
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation which may be placed on a resource/datatype definition, or a field, or
|
||||
* a search parameter definition in order to provide documentation for that item.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER, ElementType.METHOD})
|
||||
public @interface Description {
|
||||
|
||||
/**
|
||||
* Optional short name for this child
|
||||
*/
|
||||
String shortDefinition() default "";
|
||||
|
||||
/**
|
||||
* Optional formal definition for this child
|
||||
*/
|
||||
String formalDefinition() default "";
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Field modifier to be placed on a child field (a field also annotated with the {@link Child} annotation) which
|
||||
* indicates that this field is an extension.
|
||||
*/
|
||||
@Target(value = { ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Extension {
|
||||
|
||||
/**
|
||||
* This parameter affects how the extension is treated when the element definition containing this resource is
|
||||
* exported to a profile.
|
||||
*
|
||||
* <p>
|
||||
* If set to <b><code>true</code></b>, the resource is taken to be a local resource and its definition is exported
|
||||
* along with the reference. Use this option for extension defintions that you have added locally (i.e. within your
|
||||
* own organization)
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If set to <b><code>false</code></b>, the resource is taken to be a remote resource and its definition is
|
||||
* <b>not</b> exported to the profile. Use this option for extensions that are defined by other organizations (i.e.
|
||||
* by regional authorities or jurisdictional governments)
|
||||
* </p>
|
||||
*/
|
||||
boolean definedLocally();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this extension is a <a
|
||||
* href="http://www.hl7.org/implement/standards/fhir/extensibility.html#modifierExtension">modifier extension</a>
|
||||
*/
|
||||
boolean isModifier();
|
||||
|
||||
/**
|
||||
* The URL associated with this extension
|
||||
*/
|
||||
String url();
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Class annotation which indicates a resource definition class
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.TYPE})
|
||||
public @interface ResourceDef {
|
||||
|
||||
/**
|
||||
* The name of the resource (e.g. "Patient" or "DiagnosticReport")
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Not currently used
|
||||
*/
|
||||
String id() default "";
|
||||
|
||||
/**
|
||||
* The URL indicating the profile for this resource definition, if known
|
||||
*/
|
||||
String profile() default "";
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.annotations;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.hl7.fhir.dstu21.model.Resource;
|
||||
|
||||
@Target(value=ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SearchParamDefinition {
|
||||
|
||||
/**
|
||||
* The name for this parameter
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* The path for this parameter
|
||||
*/
|
||||
String path();
|
||||
|
||||
/**
|
||||
* A description of this parameter
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* The type for this parameter, e.g. "string", or "token"
|
||||
*/
|
||||
String type() default "string";
|
||||
|
||||
/**
|
||||
* If the parameter is of type "composite", this parameter lists the names of the parameters
|
||||
* which this parameter is a composite of. E.g. "name-value-token" is a composite of "name" and "value-token".
|
||||
* <p>
|
||||
* If the parameter is not a composite, this parameter must be empty
|
||||
* </p>
|
||||
*/
|
||||
String[] compositeOf() default {};
|
||||
|
||||
/**
|
||||
* For search params of type "reference", this can optionally be used to
|
||||
* specify the resource type(s) that this parameter applies to.
|
||||
*/
|
||||
Class<? extends Resource>[] target() default {};
|
||||
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IAnyResource extends IBaseResource {
|
||||
|
||||
String getId();
|
||||
|
||||
IAnyResource setId(String theId);
|
||||
|
||||
IIdType getIdElement();
|
||||
|
||||
IBaseMetaType getMeta();
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBackboneElement extends IBase {
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* This interface is a simple marker for anything which is an HL7
|
||||
* structure of some kind. It is provided mostly to simplify convergence
|
||||
* between the HL7.org structures and the HAPI ones.
|
||||
*/
|
||||
public interface IBase {
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseBackboneElement extends IBase, IBaseHasExtensions, IBaseHasModifierExtensions {
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseBinary extends IBaseResource {
|
||||
|
||||
byte[] getContent();
|
||||
|
||||
String getContentAsBase64();
|
||||
|
||||
String getContentType();
|
||||
|
||||
IBaseBinary setContent(byte[] theContent);
|
||||
|
||||
IBaseBinary setContentAsBase64(String theContent);
|
||||
|
||||
IBaseBinary setContentType(String theContentType);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseBooleanDatatype extends IPrimitiveType<Boolean> {
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseBundle extends IBaseResource {
|
||||
|
||||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* link.type field to indicate that the given link is for
|
||||
* the next page of results.
|
||||
*/
|
||||
public static final String LINK_NEXT = "next";
|
||||
|
||||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* link.type field to indicate that the given link is for
|
||||
* the previous page of results.
|
||||
*/
|
||||
public static final String LINK_PREV = "prev";
|
||||
|
||||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* link.type field to indicate that the given link is for
|
||||
* this bundle.
|
||||
*/
|
||||
public static final String LINK_SELF = "self";
|
||||
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IBaseCoding {
|
||||
|
||||
IBaseCoding setSystem(String theScheme);
|
||||
|
||||
IBaseCoding setCode(String theTerm);
|
||||
|
||||
IBaseCoding setDisplay(String theLabel);
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
public interface IBaseConformance extends IBaseResource {
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseDatatype extends IBase {
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseDatatypeElement extends IBase {
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public interface IBaseDecimalDatatype extends IPrimitiveType<BigDecimal> {
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IBaseElement {
|
||||
|
||||
IBaseElement setId(String theValue);
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IBaseEnumFactory<T extends Enum<?>> {
|
||||
|
||||
/**
|
||||
* Read an enumeration value from the string that represents it on the XML or JSON
|
||||
*
|
||||
* @param codeString the value found in the XML or JSON
|
||||
* @return the enumeration value
|
||||
* @throws IllegalArgumentException is the value is not known
|
||||
*/
|
||||
public T fromCode(String codeString) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get the XML/JSON representation for an enumerated value
|
||||
*
|
||||
* @param code - the enumeration value
|
||||
* @return the XML/JSON representation
|
||||
*/
|
||||
public String toCode(T code);
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IBaseEnumeration<T extends Enum<?>> extends IPrimitiveType<T> {
|
||||
|
||||
// Marker interface
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IBaseExtension<T, D> extends ICompositeType {
|
||||
|
||||
List<T> getExtension();
|
||||
|
||||
String getUrl();
|
||||
|
||||
IBaseDatatype getValue();
|
||||
|
||||
T setUrl(String theUrl);
|
||||
|
||||
T setValue(IBaseDatatype theValue);
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface to be implemented by all built-in FHIR enumerations (i.e. the
|
||||
* actual FHIR-defined Java Enum will implement this interface)
|
||||
*/
|
||||
public interface IBaseFhirEnum {
|
||||
|
||||
/**
|
||||
* Get the XML/JSON representation for an enumerated value
|
||||
* @return the XML/JSON representation
|
||||
*/
|
||||
public String toCode();
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IBaseHasExtensions {
|
||||
|
||||
public List<? extends IBaseExtension<?, ?>> getExtension();
|
||||
|
||||
public IBaseExtension<?, ?> addExtension();
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IBaseHasModifierExtensions {
|
||||
|
||||
public List<? extends IBaseExtension<?, ?>> getModifierExtension();
|
||||
|
||||
public IBaseExtension<?, ?> addModifierExtension();
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseIntegerDatatype extends IPrimitiveType<Integer> {
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface IBaseMetaType extends ICompositeType {
|
||||
|
||||
IBaseCoding addTag();
|
||||
|
||||
IBaseMetaType setLastUpdated(Date theHeaderDateValue);
|
||||
|
||||
Date getLastUpdated();
|
||||
|
||||
String getVersionId();
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
public interface IBaseOperationOutcome extends IBaseResource {
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseParameters extends IBaseResource {
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IBaseReference extends ICompositeType {
|
||||
|
||||
IBaseResource getResource();
|
||||
|
||||
void setResource(IBaseResource theResource);
|
||||
|
||||
IIdType getReferenceElement();
|
||||
|
||||
IBaseReference setReference(String theReference);
|
||||
|
||||
IBase setDisplay(String theValue);
|
||||
|
||||
IPrimitiveType<String> getDisplayElement();
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* For now, this is a simple marker interface indicating that a class is a resource type.
|
||||
* There are two concrete types of implementations of this interrface. The first are
|
||||
* HL7.org's Resource structures (e.g.
|
||||
* <code>org.hl7.fhir.instance.model.Patient</code>) and
|
||||
* the second are HAPI's Resource structures, e.g.
|
||||
* <code>ca.uhn.fhir.model.dstu.resource.Patient</code>)
|
||||
*/
|
||||
public interface IBaseResource extends IBase {
|
||||
|
||||
IIdType getIdElement();
|
||||
|
||||
IBaseResource setId(String theId);
|
||||
|
||||
IBaseResource setId(IIdType theId);
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
public interface IBaseXhtml extends IPrimitiveType<String> {
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface ICompositeType extends IBaseDatatype {
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IDomainResource extends IAnyResource {
|
||||
|
||||
List<? extends IAnyResource> getContained();
|
||||
|
||||
INarrative getText();
|
||||
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base interface for ID datatype.
|
||||
*
|
||||
* <p>
|
||||
* <b>Concrete Implementations:</b> This interface is often returned and/or accepted by methods in HAPI's API
|
||||
* where either {@link ca.uhn.fhir.model.primitive.IdDt} (the HAPI structure ID type) or
|
||||
* <code>org.hl7.fhir.instance.model.IdType</code> (the RI structure ID type) will be used, depending on
|
||||
* which version of the strctures your application is using.
|
||||
* </p>
|
||||
*/
|
||||
public interface IIdType {
|
||||
|
||||
void applyTo(IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* Returns the server base URL if this ID contains one. For example, the base URL is
|
||||
* the 'http://example.com/fhir' in the following ID: <code>http://example.com/fhir/Patient/123/_history/55</code>
|
||||
*/
|
||||
String getBaseUrl();
|
||||
|
||||
/**
|
||||
* Returns only the logical ID part of this ID. For example, given the ID
|
||||
* "http://example,.com/fhir/Patient/123/_history/456", this method would
|
||||
* return "123".
|
||||
*/
|
||||
String getIdPart();
|
||||
|
||||
/**
|
||||
* Returns the ID part of this ID (e.g. in the ID http://example.com/Patient/123/_history/456 this would be the
|
||||
* part "123") parsed as a {@link Long}.
|
||||
*
|
||||
* @throws NumberFormatException If the value can't be parsed as a long
|
||||
*/
|
||||
Long getIdPartAsLong();
|
||||
|
||||
String getResourceType();
|
||||
|
||||
/**
|
||||
* Returns the value of this ID. Note that this value may be a fully qualified URL, a relative/partial URL, or a simple ID. Use {@link #getIdPart()} to get just the ID portion.
|
||||
*
|
||||
* @see #getIdPart()
|
||||
*/
|
||||
String getValue();
|
||||
|
||||
String getVersionIdPart();
|
||||
|
||||
/**
|
||||
* Returns the version ID part of this ID (e.g. in the ID http://example.com/Patient/123/_history/456 this would be the
|
||||
* part "456") parsed as a {@link Long}.
|
||||
*
|
||||
* @throws NumberFormatException If the value can't be parsed as a long
|
||||
*/
|
||||
Long getVersionIdPartAsLong();
|
||||
|
||||
boolean hasBaseUrl();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an actual ID part. For example, the ID part is
|
||||
* the '123' in the following ID: <code>http://example.com/fhir/Patient/123/_history/55</code>
|
||||
*/
|
||||
boolean hasIdPart();
|
||||
|
||||
boolean hasResourceType();
|
||||
|
||||
boolean hasVersionIdPart();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an absolute URL (in other words, a URL starting with "http://" or "https://"
|
||||
*/
|
||||
boolean isAbsolute();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} is valid according to the FHIR rules for valid IDs.
|
||||
* <p>
|
||||
* The FHIR specification states:
|
||||
* <code>Any combination of upper or lower case ASCII letters ('A'..'Z', and 'a'..'z', numerals ('0'..'9'), '-' and '.', with a length limit of 64 characters. (This might be an integer, an un-prefixed OID, UUID or any other identifier pattern that meets these constraints.) regex: [A-Za-z0-9\-\.]{1,64}</code>
|
||||
* </p>
|
||||
*/
|
||||
boolean isIdPartValid();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} contains
|
||||
* only numbers
|
||||
*/
|
||||
boolean isIdPartValidLong();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the ID is a local reference (in other words, it begins with the '#' character)
|
||||
*/
|
||||
boolean isLocal();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the {@link #getVersionIdPart() version ID part of this object} contains
|
||||
* only numbers
|
||||
*/
|
||||
boolean isVersionIdPartValidLong();
|
||||
|
||||
IIdType setValue(String theString);
|
||||
|
||||
IIdType toUnqualified();
|
||||
|
||||
IIdType toUnqualifiedVersionless();
|
||||
|
||||
IIdType toVersionless();
|
||||
|
||||
IIdType withResourceType(String theResName);
|
||||
|
||||
IIdType withServerBase(String theServerBase, String theResourceName);
|
||||
|
||||
IIdType withVersion(String theVersion);
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface INarrative extends ICompositeType {
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
// TODO: use less broad exception type here
|
||||
public void setDivAsString(String theString) throws Exception;
|
||||
|
||||
// TODO: use less broad exception type here
|
||||
public String getDivAsString() throws Exception;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package org.hl7.fhir.dstu21.model.api;
|
||||
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
|
||||
public interface IPrimitiveType<T> extends IBaseDatatype {
|
||||
|
||||
void setValueAsString(String theValue) throws IllegalArgumentException;
|
||||
|
||||
String getValueAsString();
|
||||
|
||||
T getValue();
|
||||
|
||||
IPrimitiveType<T> setValue(T theValue) throws IllegalArgumentException;
|
||||
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
|
||||
import org.hl7.fhir.dstu21.model.IdType;
|
||||
import org.hl7.fhir.dstu21.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
public class RequestValidatingInterceptorTest {
|
||||
private static CloseableHttpClient ourClient;
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||
private static boolean ourLastRequestWasSearch;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestValidatingInterceptorTest.class);
|
||||
private static int ourPort;
|
||||
|
||||
private static Server ourServer;
|
||||
|
||||
private static RestfulServer ourServlet;
|
||||
|
||||
|
||||
|
||||
private RequestValidatingInterceptor myInterceptor;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourLastRequestWasSearch = false;
|
||||
while (ourServlet.getInterceptors().size() > 0) {
|
||||
ourServlet.unregisterInterceptor(ourServlet.getInterceptors().get(0));
|
||||
}
|
||||
|
||||
myInterceptor = new RequestValidatingInterceptor();
|
||||
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
// myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||
// myInterceptor.setResponseHeaderName("X-RESP");
|
||||
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
||||
|
||||
ourServlet.registerInterceptor(myInterceptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateJsonInvalidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Request-Validation"));
|
||||
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateJsonInvalidNoFailure() throws Exception {
|
||||
myInterceptor.setFailOnSeverity(null);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Request-Validation"));
|
||||
assertThat(responseContent, not(containsString("<severity value=\"error\"/>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateJsonValidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), not(containsString("X-HAPI-Request-Validation")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateJsonValidNoValidatorsSpecifiedDefaultMessage() throws Exception {
|
||||
myInterceptor.setResponseHeaderValueNoIssues("NO ISSUES");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
String encoded = ourCtx.newJsonParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), (containsString("X-HAPI-Request-Validation: NO ISSUES")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateXmlInvalidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Request-Validation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateXmlInvalidInstanceValidator() throws Exception {
|
||||
IValidatorModule module = new FhirInstanceValidator();
|
||||
myInterceptor.addValidatorModule(module);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Request-Validation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), not(containsString("X-HAPI-Request-Validation")));
|
||||
assertEquals(true, ourLastRequestWasSearch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateXmlValidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), not(containsString("X-HAPI-Request-Validation")));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
PatientProvider patientProvider = new PatientProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ourServlet = new RestfulServer(ourCtx);
|
||||
ourServlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
public static class PatientProvider implements IResourceProvider {
|
||||
|
||||
|
||||
@Create()
|
||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @IdParam IdType theIdParam) {
|
||||
return new MethodOutcome(new IdDt("Patient/001/_history/002"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<IResource> search(@OptionalParam(name="foo") StringParam theString) {
|
||||
ourLastRequestWasSearch = true;
|
||||
return new ArrayList<IResource>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
|
||||
import org.hl7.fhir.dstu21.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
public class ResponseValidatingInterceptorTest {
|
||||
private static CloseableHttpClient ourClient;
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptorTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static RestfulServer ourServlet;
|
||||
private ResponseValidatingInterceptor myInterceptor;
|
||||
public static IBaseResource myReturnResource;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myReturnResource = null;
|
||||
while (ourServlet.getInterceptors().size() > 0) {
|
||||
ourServlet.unregisterInterceptor(ourServlet.getInterceptors().get(0));
|
||||
}
|
||||
|
||||
myInterceptor = new ResponseValidatingInterceptor();
|
||||
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
// myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||
// myInterceptor.setResponseHeaderName("X-RESP");
|
||||
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
||||
|
||||
ourServlet.registerInterceptor(myInterceptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignored until #264 is fixed
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSearchJsonInvalidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Response-Validation"));
|
||||
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchJsonValidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), not(containsString("X-HAPI-Response-Validation")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchJsonValidNoValidatorsSpecifiedDefaultMessage() throws Exception {
|
||||
myInterceptor.setResponseHeaderValueNoIssues("NO ISSUES");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), (containsString("X-HAPI-Response-Validation: NO ISSUES")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignored until #264 is fixed
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSearchXmlInvalidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Response-Validation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchXmlInvalidInstanceValidator() throws Exception {
|
||||
IValidatorModule module = new FhirInstanceValidator();
|
||||
myInterceptor.addValidatorModule(module);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
patient.addContact().addRelationship().setText("FOO");
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), containsString("X-HAPI-Response-Validation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchXmlValidNoValidatorsSpecified() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
patient.setGender(AdministrativeGender.MALE);
|
||||
myReturnResource = patient;
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", status);
|
||||
ourLog.trace("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.toString(), not(containsString("X-HAPI-Response-Validation")));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
PatientProvider patientProvider = new PatientProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ourServlet = new RestfulServer(ourCtx);
|
||||
ourServlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
public static class PatientProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Search
|
||||
public ArrayList<IBaseResource> search(@OptionalParam(name="foo") StringParam theString) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
myReturnResource.setId("1");
|
||||
retVal.add(myReturnResource);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -23,8 +23,9 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||
import ca.uhn.fhir.validation.IResourceLoader;
|
||||
import ca.uhn.fhir.validation.IValidationContext;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
public class FhirQuestionnaireResponseValidator extends BaseValidatorBridge {
|
||||
public class FhirQuestionnaireResponseValidator extends BaseValidatorBridge implements IValidatorModule {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory
|
||||
.getLogger(FhirQuestionnaireResponseValidator.class);
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -597,7 +597,7 @@
|
|||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.9.0.RELEASE</version>
|
||||
<version>1.9.2.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
|
|
@ -26,6 +26,24 @@
|
|||
codebase. This dependency was accidentally introduced in
|
||||
1.3, and animal-sniffer-plugin failed to detect it (sigh).
|
||||
</action>
|
||||
<action type="add">
|
||||
Add two new server interceptors:
|
||||
<![CDATA[
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.html">RequestValidatingInterceptor</a>
|
||||
and
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.html">ResponseValidatingInterceptor</a>
|
||||
]]>
|
||||
which can be used to validate incoming requests or outgoing responses using the standard FHIR validation
|
||||
tools. See the
|
||||
<![CDATA[
|
||||
<a href="./doc_rest_server_interceptor.html#RequestResponse_Validation">Server Validation Page</a>
|
||||
]]>
|
||||
for examples of how to use these interceptors. These intereptors have both
|
||||
been enabled on the
|
||||
<![CDATA[
|
||||
<a href="http://fhirtest.uhn.ca">public test page</a>.
|
||||
]]>
|
||||
</action>
|
||||
<action type="fix" issue="259">
|
||||
Make IBoundCodeableConcept and IValueSetEnumBinder serializable,
|
||||
fixing an issue when trying to serialize model classes containing
|
||||
|
@ -78,7 +96,7 @@
|
|||
Support target parameter type in _include / _revinclude values, e.g.
|
||||
_include=Patient:careProvider:Organization. Thanks to Joe Portner
|
||||
for reporting!
|
||||
<action>
|
||||
</action>
|
||||
<action type="add">
|
||||
Use ResponseHighlighterInterceptor in the hapi-fhir-jpaserver-example
|
||||
project to provide nice syntax highlighting. Thanks to Rob Hausam for
|
||||
|
|
|
@ -251,6 +251,43 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Request/Response Validation">
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.html">RequestValidatingInterceptor</a>
|
||||
and
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.html">ResponseValidatingInterceptor</a>
|
||||
can be used to perform validation of resources on their way into and out of the server respectively.
|
||||
</p>
|
||||
<p>
|
||||
The RequestValidatingInterceptor looks at resources coming into the server (e.g. for create,
|
||||
update, $operations, transactions, etc.) and validates them. The ResponseValidatingInterceptor
|
||||
looks at resources being returned by the server (e.g. for read, search, $operations, etc.) and
|
||||
validates them.
|
||||
</p>
|
||||
<p>
|
||||
These interceptors can be configured to add headers to the response, fail the response
|
||||
(returning an HTTP 422 and throwing an exception in the process), or to add to the
|
||||
OperationOutcome returned by the server.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="./doc_validation.html">Validation Page</a> for information on
|
||||
available IValidationModule validation modules. Any of the <b>Resource Validators</b>
|
||||
listed on that page can be enabled in these interceptors (note that the <b>Parser Validators</b>
|
||||
can not).
|
||||
</p>
|
||||
<p>
|
||||
The following example shows how to register this interceptor within
|
||||
a FHIR RESTful server.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="validatingInterceptor" />
|
||||
<param name="file" value="examples/src/main/java/example/ServletExamples.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Creating Interceptors">
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
of a resource. It can be used to catch input data that is impossible to
|
||||
fit into the HAPI data model. For
|
||||
example, it can be used to throw exceptions
|
||||
or display error messages if a resource being parsed contains tags for which
|
||||
there are no appropriate fields in a HAPI data structure.
|
||||
or display error messages if a resource being parsed contains elements for which
|
||||
there are no appropriate fields in a HAPI data structure. This is useful in order to ensure
|
||||
that no data is being lost during parsing, but is less comprehensive than resource validation
|
||||
against raw text data.
|
||||
</li>
|
||||
<li>
|
||||
<b>Resource Validation</b>
|
||||
is validation of the parsed (or constructed) resource against
|
||||
is validation of the raw or parsed resource against
|
||||
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet).
|
||||
</li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue