Enable validation ($validate) operation in DSTU2 style
This commit is contained in:
parent
e5b402cb14
commit
9b97fb0e97
|
@ -59,6 +59,7 @@ import ca.uhn.fhir.rest.annotation.Validate;
|
|||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
|
@ -836,7 +837,9 @@ public abstract MethodOutcome updateSomePatient(@IdParam IdDt theId, @ResourcePa
|
|||
|
||||
//START SNIPPET: validate
|
||||
@Validate
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient) {
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient,
|
||||
@Validate.Mode ValidationModeEnum theMode,
|
||||
@Validate.Profile String theProfile) {
|
||||
|
||||
// Actually do our validation: The UnprocessableEntityException
|
||||
// results in an HTTP 422, which is appropriate for business rule failure
|
||||
|
|
|
@ -66,6 +66,16 @@ public class BuiltJarIT {
|
|||
}
|
||||
|
||||
for (File file : files) {
|
||||
if (file.getName().endsWith("sources.jar")) {
|
||||
continue;
|
||||
}
|
||||
if (file.getName().endsWith("javadoc.jar")) {
|
||||
continue;
|
||||
}
|
||||
if (file.getName().contains("original.jar")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ourLog.info("Testing file: {}", file);
|
||||
|
||||
ZipFile zip = new ZipFile(file);
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adapter implementation with NOP implementations of all {@link IParserErrorHandler} methods.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error handler
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default error handler, which logs issues but does not abort parsing
|
||||
*
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parser error handler which throws a {@link DataFormatException} any time an
|
||||
* issue is found while parsing.
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
/**
|
||||
|
@ -36,6 +37,12 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
|||
* Validate is used to accept a resource, and test whether it would be acceptable for
|
||||
* storing (e.g. using an update or create method)
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>FHIR Version Note:</b> The validate operation was defined as a type operation in DSTU1
|
||||
* using a URL syntax like <code>http://example.com/Patient/_validate</code>. In DSTU2, validation
|
||||
* has been switched to being an extended operation using a URL syntax like
|
||||
* <code>http://example.com/Patient/$validate</code>, with a n
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value=ElementType.METHOD)
|
||||
|
@ -50,4 +57,24 @@ public @interface Validate {
|
|||
// NB: Read, Search (maybe others) share this annotation, so update the javadocs everywhere
|
||||
Class<? extends IResource> type() default IResource.class;
|
||||
|
||||
/**
|
||||
* Validation mode parameter annotation for the validation mode parameter (only supported
|
||||
* in FHIR DSTU2+). Parameter must be of type {@link ValidationModeEnum}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@interface Mode {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation mode parameter annotation for the validation URI parameter (only supported
|
||||
* in FHIR DSTU2+). Parameter must be of type {@link String}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@interface Profile {
|
||||
// nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package ca.uhn.fhir.rest.api;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
|
||||
/**
|
||||
* Validation mode parameter for the $validate operation (DSTU2+ only)
|
||||
*/
|
||||
public enum ValidationModeEnum implements IBase {
|
||||
/**
|
||||
* The server checks the content, and then checks that the content would be acceptable as a create (e.g. that the content would not validate any uniqueness constraints)
|
||||
*/
|
||||
CREATE,
|
||||
|
||||
/**
|
||||
* The server checks the content, and then checks that it would accept it as an update against the nominated specific resource (e.g. that there are no changes to immutable fields the server does not allow to change, and checking version integrity if appropriate)
|
||||
*/
|
||||
UPDATE,
|
||||
|
||||
/**
|
||||
* The server ignores the content, and checks that the nominated resource is allowed to be deleted (e.g. checking referential integrity rules)
|
||||
*/
|
||||
DELETE;
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.client;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -116,7 +117,7 @@ import ca.uhn.fhir.rest.method.ReadMethodBinding;
|
|||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
import ca.uhn.fhir.rest.method.TransactionMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu1;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
|
@ -507,7 +508,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public MethodOutcome validate(IResource theResource) {
|
||||
BaseHttpClientInvocation invocation = ValidateMethodBinding.createValidateInvocation(theResource, null, myContext);
|
||||
BaseHttpClientInvocation invocation = ValidateMethodBindingDstu1.createValidateInvocation(theResource, null, myContext);
|
||||
if (isKeepResponses()) {
|
||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
Object[] params = createParametersForServerRequest(theRequest, null);
|
||||
|
||||
params[myIdParamIndex] = theRequest.getId();
|
||||
|
@ -199,7 +199,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (theRequest.getRequestType() != RequestTypeEnum.POST) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
|
@ -110,7 +111,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return parser;
|
||||
}
|
||||
|
||||
protected IParser createAppropriateParserForParsingServerRequest(Request theRequest) {
|
||||
protected IParser createAppropriateParserForParsingServerRequest(RequestDetails theRequest) {
|
||||
String contentTypeHeader = theRequest.getServletRequest().getHeader("content-type");
|
||||
EncodingEnum encoding;
|
||||
if (isBlank(contentTypeHeader)) {
|
||||
|
@ -131,7 +132,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return parser;
|
||||
}
|
||||
|
||||
protected Object[] createParametersForServerRequest(Request theRequest, byte[] theRequestContents) {
|
||||
protected Object[] createParametersForServerRequest(RequestDetails theRequest, byte[] theRequestContents) {
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
IParameter param = getParameters().get(i);
|
||||
|
@ -241,11 +242,11 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
|
||||
public abstract RestfulOperationSystemEnum getSystemOperationType();
|
||||
|
||||
public abstract boolean incomingServerRequestMatchesMethod(Request theRequest);
|
||||
public abstract boolean incomingServerRequestMatchesMethod(RequestDetails theRequest);
|
||||
|
||||
public abstract BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException;
|
||||
|
||||
public abstract void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException;
|
||||
public abstract void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException;
|
||||
|
||||
protected Object invokeServerMethod(Object[] theMethodParams) {
|
||||
try {
|
||||
|
@ -262,7 +263,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
}
|
||||
|
||||
protected byte[] loadRequestContents(Request theRequest) throws IOException {
|
||||
protected byte[] loadRequestContents(RequestDetails theRequest) throws IOException {
|
||||
byte[] requestContents = IOUtils.toByteArray(theRequest.getServletRequest().getInputStream());
|
||||
return requestContents;
|
||||
}
|
||||
|
@ -305,6 +306,30 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
myParameters = theParameters;
|
||||
}
|
||||
|
||||
protected IBundleProvider toResourceList(Object response) throws InternalErrorException {
|
||||
if (response == null) {
|
||||
return BundleProviders.newEmptyList();
|
||||
} else if (response instanceof IBundleProvider) {
|
||||
return (IBundleProvider) response;
|
||||
} else if (response instanceof IResource) {
|
||||
return BundleProviders.newList((IResource) response);
|
||||
} else if (response instanceof Collection) {
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
for (Object next : ((Collection<?>) response)) {
|
||||
retVal.add((IBaseResource) next);
|
||||
}
|
||||
return BundleProviders.newList(retVal);
|
||||
} else if (response instanceof MethodOutcome) {
|
||||
IBaseResource retVal = ((MethodOutcome) response).getOperationOutcome();
|
||||
if (retVal == null) {
|
||||
retVal = getContext().getResourceDefinition("OperationOutcome").newInstance();
|
||||
}
|
||||
return BundleProviders.newList(retVal);
|
||||
} else {
|
||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static BaseMethodBinding<?> bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
Read read = theMethod.getAnnotation(Read.class);
|
||||
|
@ -438,7 +463,11 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
} else if (history != null) {
|
||||
return new HistoryMethodBinding(theMethod, theContext, theProvider);
|
||||
} else if (validate != null) {
|
||||
return new ValidateMethodBinding(theMethod, theContext, theProvider);
|
||||
if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
return new ValidateMethodBindingDstu1(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
return new ValidateMethodBindingDstu2(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
|
||||
}
|
||||
} else if (getTags != null) {
|
||||
return new GetTagsMethodBinding(theMethod, theContext, theProvider, getTags);
|
||||
} else if (addTags != null) {
|
||||
|
@ -491,24 +520,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return theType.getCanonicalName();
|
||||
}
|
||||
|
||||
protected static IBundleProvider toResourceList(Object response) throws InternalErrorException {
|
||||
if (response == null) {
|
||||
return BundleProviders.newEmptyList();
|
||||
} else if (response instanceof IBundleProvider) {
|
||||
return (IBundleProvider) response;
|
||||
} else if (response instanceof IResource) {
|
||||
return BundleProviders.newList((IResource) response);
|
||||
} else if (response instanceof Collection) {
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
for (Object next : ((Collection<?>) response)) {
|
||||
retVal.add((IBaseResource) next);
|
||||
}
|
||||
return BundleProviders.newList(retVal);
|
||||
} else {
|
||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean verifyIsValidResourceReturnType(Class<?> theReturnType) {
|
||||
if (theReturnType == null) {
|
||||
return false;
|
||||
|
|
|
@ -67,7 +67,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
}
|
||||
|
||||
private void addLocationHeader(Request theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation) {
|
||||
private void addLocationHeader(RequestDetails theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theRequest.getFhirServerBase());
|
||||
b.append('/');
|
||||
|
@ -84,7 +84,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
theResponse.addHeader(headerLocation, b.toString());
|
||||
}
|
||||
|
||||
protected abstract void addParametersForServerRequest(Request theRequest, Object[] theParams);
|
||||
protected abstract void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams);
|
||||
|
||||
/**
|
||||
* Subclasses may override to allow a void method return type, which is allowable for some methods (e.g. delete)
|
||||
|
@ -101,7 +101,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
protected abstract String getMatchingOperation();
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
Set<RequestTypeEnum> allowableRequestTypes = provideAllowableRequestTypes();
|
||||
RequestTypeEnum requestType = theRequest.getRequestType();
|
||||
if (!allowableRequestTypes.contains(requestType)) {
|
||||
|
@ -120,8 +120,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
|
||||
@Override
|
||||
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||
BaseServerResponseException {
|
||||
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:
|
||||
|
@ -138,7 +137,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
byte[] requestContents = loadRequestContents(theRequest);
|
||||
// if (requestContainsResource()) {
|
||||
// requestContents = parseIncomingServerResource(theRequest);
|
||||
|
@ -243,7 +242,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
// getMethod().in
|
||||
}
|
||||
|
||||
private void addContentLocationHeaders(Request theRequest, HttpServletResponse servletResponse, MethodOutcome response) {
|
||||
private void addContentLocationHeaders(RequestDetails theRequest, HttpServletResponse servletResponse, MethodOutcome response) {
|
||||
if (response != null && response.getId() != null) {
|
||||
addLocationHeader(theRequest, servletResponse, response, Constants.HEADER_LOCATION);
|
||||
addLocationHeader(theRequest, servletResponse, response, Constants.HEADER_CONTENT_LOCATION);
|
||||
|
@ -256,7 +255,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
protected abstract Set<RequestTypeEnum> provideAllowableRequestTypes();
|
||||
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, Request theRequest)
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest)
|
||||
throws IOException {
|
||||
theResponse.setStatus(theE.getStatusCode());
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
|
||||
if (myIdParamIndex != null) {
|
||||
theParams[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -45,8 +45,10 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
@ -112,6 +114,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
|
||||
} else if (IBundleProvider.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE_PROVIDER;
|
||||
} else if (MethodOutcome.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.METHOD_OUTCOME;
|
||||
} else {
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: "
|
||||
+ theMethod.getDeclaringClass().getCanonicalName());
|
||||
|
@ -151,7 +155,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
public abstract ReturnTypeEnum getReturnType();
|
||||
|
||||
@Override
|
||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException {
|
||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) {
|
||||
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
|
||||
|
||||
switch (getReturnType()) {
|
||||
|
@ -191,6 +195,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
case BUNDLE_PROVIDER:
|
||||
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -213,6 +219,13 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
return resource;
|
||||
case BUNDLE_PROVIDER:
|
||||
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients");
|
||||
case BUNDLE_RESOURCE:
|
||||
// TODO: we should support this
|
||||
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not yet supported in clients");
|
||||
case METHOD_OUTCOME:
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) resource);
|
||||
return retVal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -224,7 +237,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
public abstract Object invokeServer(RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
|
||||
// Pretty print
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
|
@ -351,7 +364,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
return;
|
||||
}
|
||||
}
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode,
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode,
|
||||
Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), isAddContentLocationHeader());
|
||||
}
|
||||
|
||||
|
@ -395,7 +408,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
|
||||
public enum MethodReturnTypeEnum {
|
||||
BUNDLE, BUNDLE_PROVIDER, BUNDLE_RESOURCE, LIST_OF_RESOURCES, RESOURCE
|
||||
BUNDLE, BUNDLE_PROVIDER, BUNDLE_RESOURCE, LIST_OF_RESOURCES, RESOURCE, METHOD_OUTCOME
|
||||
}
|
||||
|
||||
public enum ReturnTypeEnum {
|
||||
|
|
|
@ -51,7 +51,7 @@ class ConditionalParamBinder implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
if (myOperationType == RestfulOperationTypeEnum.CREATE) {
|
||||
String retVal = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_EXIST);
|
||||
|
|
|
@ -75,7 +75,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.OPTIONS) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class CountParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||
if (sinceParams != null) {
|
||||
if (sinceParams.length > 0) {
|
||||
|
|
|
@ -143,7 +143,7 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
|
||||
theParams[myIdParameterIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public class DynamicSearchMethodBinding extends BaseResourceReturningMethodBindi
|
|||
List<IParameter> retVal = new ArrayList<IParameter>(super.getParameters());
|
||||
|
||||
for (RuntimeSearchParam next : mySearchParameters) {
|
||||
|
||||
// TODO: what is this?
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
@ -108,7 +108,7 @@ public class DynamicSearchMethodBinding extends BaseResourceReturningMethodBindi
|
|||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DynamicSearchMethodBinding.class);
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (!theRequest.getResourceName().equals(getResourceName())) {
|
||||
ourLog.trace("Method {} doesn't match because resource name {} != {}", getMethod().getName(), theRequest.getResourceName(), getResourceName());
|
||||
return false;
|
||||
|
|
|
@ -44,6 +44,7 @@ import ca.uhn.fhir.rest.param.StringOrListParam;
|
|||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.UriOrListParam;
|
||||
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -66,7 +67,7 @@ public class DynamicSearchParameter implements IParameter {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
SearchParameterMap retVal = new SearchParameterMap();
|
||||
|
||||
for (String next : theRequest.getParameters().keySet()) {
|
||||
|
@ -133,6 +134,11 @@ public class DynamicSearchParameter implements IParameter {
|
|||
tokenOrListParam.setValuesAsQueryTokens(paramList);
|
||||
retVal.add(next, tokenOrListParam);
|
||||
break;
|
||||
case URI:
|
||||
UriOrListParam uriOrListParam = new UriOrListParam();
|
||||
uriOrListParam.setValuesAsQueryTokens(paramList);
|
||||
retVal.add(next, uriOrListParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
|
||||
if (theResponseStatusCode == Constants.STATUS_HTTP_200_OK) {
|
||||
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
|
||||
TagList retVal = parser.parseTagList(theResponseReader);
|
||||
|
@ -148,7 +148,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
Object[] params = createParametersForServerRequest(theRequest, null);
|
||||
|
||||
if (myIdParamIndex != null) {
|
||||
|
@ -188,7 +188,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (theRequest.getRequestType()!=RequestTypeEnum.GET) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
// ObjectUtils.equals is replaced by a JDK7 method..
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (!Constants.PARAM_HISTORY.equals(theRequest.getOperation())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public interface IParameter {
|
|||
* @param theMethodBinding TODO
|
||||
* @return Returns the argument object as it will be passed to the {@link IResourceProvider} method.
|
||||
*/
|
||||
Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException;
|
||||
Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType);
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
|||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
|
@ -64,9 +65,12 @@ import ca.uhn.fhir.rest.annotation.Since;
|
|||
import ca.uhn.fhir.rest.annotation.Sort;
|
||||
import ca.uhn.fhir.rest.annotation.TagListParam;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.OperationParameter.IConverter;
|
||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||
import ca.uhn.fhir.rest.param.DateAndListParam;
|
||||
import ca.uhn.fhir.rest.param.NumberAndListParam;
|
||||
|
@ -436,7 +440,37 @@ public class MethodUtil {
|
|||
param = new ConditionalParamBinder(theRestfulOperationTypeEnum);
|
||||
} else if (nextAnnotation instanceof OperationParam) {
|
||||
Operation op = theMethod.getAnnotation(Operation.class);
|
||||
param = new OperationParameter(op.name(), (OperationParam) nextAnnotation);
|
||||
param = new OperationParameter(op.name(), ((OperationParam) nextAnnotation).name());
|
||||
} else if (nextAnnotation instanceof Validate.Mode) {
|
||||
if (parameterType.equals(ValidationModeEnum.class) == false) {
|
||||
throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Mode.class.getSimpleName() + " must be of type " + ValidationModeEnum.class.getName());
|
||||
}
|
||||
param = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_MODE).setConverter(new IConverter() {
|
||||
@Override
|
||||
public Object outgoingClient(Object theObject) {
|
||||
return new StringDt(((ValidationModeEnum)theObject).name().toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object incomingServer(Object theObject) {
|
||||
return ValidationModeEnum.valueOf(theObject.toString().toUpperCase());
|
||||
}
|
||||
});
|
||||
} else if (nextAnnotation instanceof Validate.Profile) {
|
||||
if (parameterType.equals(String.class) == false) {
|
||||
throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Profile.class.getSimpleName() + " must be of type " + String.class.getName());
|
||||
}
|
||||
param = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_PROFILE).setConverter(new IConverter() {
|
||||
@Override
|
||||
public Object outgoingClient(Object theObject) {
|
||||
return new StringDt(theObject.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object incomingServer(Object theObject) {
|
||||
return theObject.toString();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class NarrativeModeParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String val = theRequest.getServletRequest().getParameter(Constants.PARAM_NARRATIVE);
|
||||
if (val != null) {
|
||||
try {
|
||||
|
|
|
@ -39,7 +39,7 @@ class NullParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
// nothing
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -59,23 +59,28 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
private final Integer myIdParamIndex;
|
||||
private final String myName;
|
||||
private final ReturnTypeEnum myReturnType;
|
||||
private final OtherOperationTypeEnum myOtherOperatiopnType;
|
||||
|
||||
public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Operation theAnnotation) {
|
||||
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type());
|
||||
}
|
||||
|
||||
public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider, boolean theIdempotent, String theOperationName,
|
||||
Class<? extends IBaseResource> theOperationType) {
|
||||
super(theReturnResourceType, theMethod, theContext, theProvider);
|
||||
|
||||
myHttpGetPermitted = theAnnotation.idempotent();
|
||||
myHttpGetPermitted = theIdempotent;
|
||||
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod);
|
||||
|
||||
String name = theAnnotation.name();
|
||||
if (isBlank(name)) {
|
||||
if (isBlank(theOperationName)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName()
|
||||
+ " but this annotation has no name defined");
|
||||
}
|
||||
if (name.startsWith("$") == false) {
|
||||
name = "$" + name;
|
||||
if (theOperationName.startsWith("$") == false) {
|
||||
theOperationName = "$" + theOperationName;
|
||||
}
|
||||
myName = name;
|
||||
myName = theOperationName;
|
||||
|
||||
if (theContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU1)) {
|
||||
throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name());
|
||||
|
@ -84,8 +89,8 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
if (theReturnTypeFromRp != null) {
|
||||
setResourceName(theContext.getResourceDefinition(theReturnTypeFromRp).getName());
|
||||
} else {
|
||||
if (Modifier.isAbstract(theAnnotation.type().getModifiers()) == false) {
|
||||
setResourceName(theContext.getResourceDefinition(theAnnotation.type()).getName());
|
||||
if (Modifier.isAbstract(theOperationType.getModifiers()) == false) {
|
||||
setResourceName(theContext.getResourceDefinition(theOperationType).getName());
|
||||
} else {
|
||||
setResourceName(null);
|
||||
}
|
||||
|
@ -102,6 +107,18 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
myReturnType = ReturnTypeEnum.RESOURCE;
|
||||
}
|
||||
|
||||
if (getResourceName() == null) {
|
||||
myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_SERVER;
|
||||
} else if (myIdParamIndex == null) {
|
||||
myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_TYPE;
|
||||
} else {
|
||||
myOtherOperatiopnType = OtherOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OtherOperationTypeEnum getOtherOperationType() {
|
||||
return myOtherOperatiopnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,7 +142,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (getResourceName() == null) {
|
||||
if (isNotBlank(theRequest.getResourceName())) {
|
||||
return false;
|
||||
|
|
|
@ -41,43 +41,25 @@ import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||
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.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
|
||||
class OperationParameter implements IParameter {
|
||||
|
||||
private final String myName;
|
||||
private Class<?> myParameterType;
|
||||
private IConverter myConverter;
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Class<? extends Collection> myInnerCollectionType;
|
||||
private final String myName;
|
||||
private final String myOperationName;
|
||||
private Class<?> myParameterType;
|
||||
|
||||
OperationParameter(String theOperationName, OperationParam theAnnotation) {
|
||||
OperationParameter(String theOperationName, String theParameterName) {
|
||||
myOperationName = theOperationName;
|
||||
myName = theAnnotation.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
|
||||
throws InternalErrorException {
|
||||
assert theTargetResource != null;
|
||||
if (theSourceClientArgument == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
|
||||
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
|
||||
addClientParameter(theContext, theSourceClientArgument, theTargetResource, paramChild, paramChildElem);
|
||||
myName = theParameterName;
|
||||
}
|
||||
|
||||
private void addClientParameter(FhirContext theContext, Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
|
||||
|
@ -96,7 +78,7 @@ class OperationParameter implements IParameter {
|
|||
throw new IllegalArgumentException("Don't know how to handle value of type " + theSourceClientArgument.getClass() + " for paramater " + myName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem) {
|
||||
IBase parameter = paramChildElem.newInstance();
|
||||
paramChild.getMutator().addValue(theTargetResource, parameter);
|
||||
|
@ -110,9 +92,43 @@ class OperationParameter implements IParameter {
|
|||
return parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
myParameterType = theParameterType;
|
||||
if (theInnerCollectionType != null) {
|
||||
myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, myName);
|
||||
}
|
||||
}
|
||||
|
||||
public OperationParameter setConverter(IConverter theConverter) {
|
||||
myConverter = theConverter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
|
||||
throws InternalErrorException {
|
||||
assert theTargetResource != null;
|
||||
Object sourceClientArgument = theSourceClientArgument;
|
||||
if (sourceClientArgument == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myConverter != null) {
|
||||
sourceClientArgument = myConverter.outgoingClient(sourceClientArgument);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
|
||||
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
|
||||
addClientParameter(theContext, sourceClientArgument, theTargetResource, paramChild, paramChildElem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
List<Object> matchingParamValues = new ArrayList<Object>();
|
||||
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
|
@ -199,10 +215,13 @@ class OperationParameter implements IParameter {
|
|||
}
|
||||
|
||||
private void tryToAddValues(List<IBase> theParamValues, List<Object> theMatchingParamValues) {
|
||||
for (IBase nextValue : theParamValues) {
|
||||
for (Object nextValue : theParamValues) {
|
||||
if (nextValue == null) {
|
||||
continue;
|
||||
}
|
||||
if (myConverter != null) {
|
||||
nextValue = myConverter.incomingServer(nextValue);
|
||||
}
|
||||
if (!myParameterType.isAssignableFrom(nextValue.getClass())) {
|
||||
throw new InvalidRequestException("Request has parameter " + myName + " of type " + nextValue.getClass().getSimpleName() + " but method expects type "
|
||||
+ myParameterType.getSimpleName());
|
||||
|
@ -211,12 +230,12 @@ class OperationParameter implements IParameter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
myParameterType = theParameterType;
|
||||
if (theInnerCollectionType != null) {
|
||||
myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, myName);
|
||||
}
|
||||
}
|
||||
public interface IConverter {
|
||||
|
||||
Object incomingServer(Object theObject);
|
||||
|
||||
Object outgoingClient(Object theObject);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,8 +30,23 @@ public enum OtherOperationTypeEnum {
|
|||
|
||||
GET_TAGS("get-tags"),
|
||||
|
||||
GET_PAGE("get-page");
|
||||
|
||||
GET_PAGE("get-page"),
|
||||
|
||||
/**
|
||||
* E.g. $everything, $validate, etc.
|
||||
*/
|
||||
EXTENDED_OPERATION_SERVER("extended-operation-server"),
|
||||
|
||||
/**
|
||||
* E.g. $everything, $validate, etc.
|
||||
*/
|
||||
EXTENDED_OPERATION_TYPE("extended-operation-type"),
|
||||
|
||||
/**
|
||||
* E.g. $everything, $validate, etc.
|
||||
*/
|
||||
EXTENDED_OPERATION_INSTANCE("extended-operation-instance");
|
||||
|
||||
private String myCode;
|
||||
|
||||
OtherOperationTypeEnum(String theName) {
|
||||
|
|
|
@ -110,7 +110,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (!theRequest.getResourceName().equals(getResourceName())) {
|
||||
return false;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
case RESOURCE:
|
||||
return resource;
|
||||
case BUNDLE_PROVIDER:
|
||||
return new SimpleBundleProvider((IResource) resource);
|
||||
return new SimpleBundleProvider(resource);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("" + getMethodReturnType()); // should not happen
|
||||
|
@ -203,7 +203,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
IBundleProvider retVal = toResourceList(response);
|
||||
|
||||
if (theRequest.getServer().getETagSupport() == ETagSupportEnum.ENABLED) {
|
||||
String ifNoneMatch = ((Request)theRequest).getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
|
||||
String ifNoneMatch = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
|
||||
if (retVal.size() == 1 && StringUtils.isNotBlank(ifNoneMatch)) {
|
||||
List<IBaseResource> responseResources = retVal.getResources(0, 1);
|
||||
IBaseResource responseResource = responseResources.get(0);
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
|
||||
/**
|
||||
* This class is internal to HAPI - Use with caution as methods may change in future versions of the library
|
||||
*/
|
||||
public class Request extends RequestDetails {
|
||||
|
||||
private String myFhirServerBase;
|
||||
private String myOperation;
|
||||
private String myRequestPath;
|
||||
private boolean myRespondGzip;
|
||||
private String mySecondaryOperation;
|
||||
private HttpServletRequest myServletRequest;
|
||||
private HttpServletResponse myServletResponse;
|
||||
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
|
||||
|
||||
public String getFhirServerBase() {
|
||||
return myFhirServerBase;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return myOperation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The part of the request URL that comes after the server base.
|
||||
* <p>
|
||||
* Will not contain a leading '/'
|
||||
* </p>
|
||||
*/
|
||||
public String getRequestPath() {
|
||||
return myRequestPath;
|
||||
}
|
||||
|
||||
public String getSecondaryOperation() {
|
||||
return mySecondaryOperation;
|
||||
}
|
||||
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return myServletRequest;
|
||||
}
|
||||
|
||||
public HttpServletResponse getServletResponse() {
|
||||
return myServletResponse;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
|
||||
return myUnqualifiedToQualifiedNames;
|
||||
}
|
||||
|
||||
public boolean isRespondGzip() {
|
||||
return myRespondGzip;
|
||||
}
|
||||
|
||||
public void setFhirServerBase(String theFhirServerBase) {
|
||||
myFhirServerBase = theFhirServerBase;
|
||||
}
|
||||
|
||||
public void setOperation(String theOperation) {
|
||||
myOperation = theOperation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameters(Map<String, String[]> theParams) {
|
||||
super.setParameters(theParams);
|
||||
|
||||
for (String next : theParams.keySet()) {
|
||||
for (int i = 0; i < next.length(); i++) {
|
||||
char nextChar = next.charAt(i);
|
||||
if (nextChar == ':' || nextChar == '.') {
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = new HashMap<String, List<String>>();
|
||||
}
|
||||
String unqualified = next.substring(0, i);
|
||||
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>(4);
|
||||
myUnqualifiedToQualifiedNames.put(unqualified, list);
|
||||
}
|
||||
list.add(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setRequestPath(String theRequestPath) {
|
||||
assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
|
||||
myRequestPath = theRequestPath;
|
||||
}
|
||||
|
||||
public void setRespondGzip(boolean theRespondGzip) {
|
||||
myRespondGzip = theRespondGzip;
|
||||
}
|
||||
|
||||
public void setSecondaryOperation(String theSecondaryOperation) {
|
||||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
public void setServletRequest(HttpServletRequest theRequest) {
|
||||
myServletRequest = theRequest;
|
||||
}
|
||||
|
||||
public void setServletResponse(HttpServletResponse theServletResponse) {
|
||||
myServletResponse = theServletResponse;
|
||||
}
|
||||
|
||||
public static Request withResourceAndParams(String theResourceName, RequestTypeEnum theRequestType, Set<String> theParamNames) {
|
||||
Request retVal = new Request();
|
||||
retVal.setResourceName(theResourceName);
|
||||
retVal.setRequestType(theRequestType);
|
||||
Map<String, String[]> paramNames = new HashMap<String, String[]>();
|
||||
for (String next : theParamNames) {
|
||||
paramNames.put(next, new String[0]);
|
||||
}
|
||||
retVal.setParameters(paramNames);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,15 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
|
@ -32,14 +40,22 @@ public class RequestDetails {
|
|||
|
||||
private String myCompartmentName;
|
||||
private String myCompleteUrl;
|
||||
private String myFhirServerBase;
|
||||
private IdDt myId;
|
||||
private String myOperation;
|
||||
private OtherOperationTypeEnum myOtherOperationType;
|
||||
private Map<String, String[]> myParameters;
|
||||
private String myRequestPath;
|
||||
private RequestTypeEnum myRequestType;
|
||||
private String myResourceName;
|
||||
private RestfulOperationTypeEnum myResourceOperationType;
|
||||
private boolean myRespondGzip;
|
||||
private String mySecondaryOperation;
|
||||
private RestfulServer myServer;
|
||||
private HttpServletRequest myServletRequest;
|
||||
private HttpServletResponse myServletResponse;
|
||||
private RestfulOperationSystemEnum mySystemOperationType;
|
||||
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
|
||||
|
||||
public String getCompartmentName() {
|
||||
return myCompartmentName;
|
||||
|
@ -49,10 +65,18 @@ public class RequestDetails {
|
|||
return myCompleteUrl;
|
||||
}
|
||||
|
||||
public String getFhirServerBase() {
|
||||
return myFhirServerBase;
|
||||
}
|
||||
|
||||
public IdDt getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return myOperation;
|
||||
}
|
||||
|
||||
public OtherOperationTypeEnum getOtherOperationType() {
|
||||
return myOtherOperationType;
|
||||
}
|
||||
|
@ -61,6 +85,16 @@ public class RequestDetails {
|
|||
return myParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* The part of the request URL that comes after the server base.
|
||||
* <p>
|
||||
* Will not contain a leading '/'
|
||||
* </p>
|
||||
*/
|
||||
public String getRequestPath() {
|
||||
return myRequestPath;
|
||||
}
|
||||
|
||||
public RequestTypeEnum getRequestType() {
|
||||
return myRequestType;
|
||||
}
|
||||
|
@ -73,14 +107,34 @@ public class RequestDetails {
|
|||
return myResourceOperationType;
|
||||
}
|
||||
|
||||
public String getSecondaryOperation() {
|
||||
return mySecondaryOperation;
|
||||
}
|
||||
|
||||
public RestfulServer getServer() {
|
||||
return myServer;
|
||||
}
|
||||
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return myServletRequest;
|
||||
}
|
||||
|
||||
public HttpServletResponse getServletResponse() {
|
||||
return myServletResponse;
|
||||
}
|
||||
|
||||
public RestfulOperationSystemEnum getSystemOperationType() {
|
||||
return mySystemOperationType;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
|
||||
return myUnqualifiedToQualifiedNames;
|
||||
}
|
||||
|
||||
public boolean isRespondGzip() {
|
||||
return myRespondGzip;
|
||||
}
|
||||
|
||||
public void setCompartmentName(String theCompartmentName) {
|
||||
myCompartmentName = theCompartmentName;
|
||||
}
|
||||
|
@ -89,16 +143,53 @@ public class RequestDetails {
|
|||
myCompleteUrl = theCompleteUrl;
|
||||
}
|
||||
|
||||
public void setFhirServerBase(String theFhirServerBase) {
|
||||
myFhirServerBase = theFhirServerBase;
|
||||
}
|
||||
|
||||
public void setId(IdDt theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
public void setOperation(String theOperation) {
|
||||
myOperation = theOperation;
|
||||
}
|
||||
|
||||
public void setOtherOperationType(OtherOperationTypeEnum theOtherOperationType) {
|
||||
myOtherOperationType = theOtherOperationType;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String[]> theParams) {
|
||||
myParameters = theParams;
|
||||
|
||||
for (String next : theParams.keySet()) {
|
||||
for (int i = 0; i < next.length(); i++) {
|
||||
char nextChar = next.charAt(i);
|
||||
if (nextChar == ':' || nextChar == '.') {
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = new HashMap<String, List<String>>();
|
||||
}
|
||||
String unqualified = next.substring(0, i);
|
||||
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>(4);
|
||||
myUnqualifiedToQualifiedNames.put(unqualified, list);
|
||||
}
|
||||
list.add(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setRequestPath(String theRequestPath) {
|
||||
assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
|
||||
myRequestPath = theRequestPath;
|
||||
}
|
||||
|
||||
public void setRequestType(RequestTypeEnum theRequestType) {
|
||||
|
@ -113,12 +204,40 @@ public class RequestDetails {
|
|||
myResourceOperationType = theResourceOperationType;
|
||||
}
|
||||
|
||||
public void setRespondGzip(boolean theRespondGzip) {
|
||||
myRespondGzip = theRespondGzip;
|
||||
}
|
||||
|
||||
public void setSecondaryOperation(String theSecondaryOperation) {
|
||||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
public void setServer(RestfulServer theServer) {
|
||||
myServer = theServer;
|
||||
}
|
||||
|
||||
public void setServletRequest(HttpServletRequest theRequest) {
|
||||
myServletRequest = theRequest;
|
||||
}
|
||||
|
||||
public void setServletResponse(HttpServletResponse theServletResponse) {
|
||||
myServletResponse = theServletResponse;
|
||||
}
|
||||
|
||||
public void setSystemOperationType(RestfulOperationSystemEnum theSystemOperationType) {
|
||||
mySystemOperationType = theSystemOperationType;
|
||||
}
|
||||
|
||||
public static RequestDetails withResourceAndParams(String theResourceName, RequestTypeEnum theRequestType, Set<String> theParamNames) {
|
||||
RequestDetails retVal = new RequestDetails();
|
||||
retVal.setResourceName(theResourceName);
|
||||
retVal.setRequestType(theRequestType);
|
||||
Map<String, String[]> paramNames = new HashMap<String, String[]>();
|
||||
for (String next : theParamNames) {
|
||||
paramNames.put(next, new String[0]);
|
||||
}
|
||||
retVal.setParameters(paramNames);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (!theRequest.getResourceName().equals(getResourceName())) {
|
||||
ourLog.trace("Method {} doesn't match because resource name {} != {}", getMethod().getName(), theRequest.getResourceName(), getResourceName());
|
||||
return false;
|
||||
|
|
|
@ -43,7 +43,7 @@ class ServerBaseParamBinder implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getFhirServerBase();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class ServletRequestParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getServletRequest();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class ServletResponseParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getServletResponse();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class SinceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
String[] sinceParams = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||
if (sinceParams != null) {
|
||||
if (sinceParams.length > 0) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class SortParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT)) {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_ASC)) {
|
||||
if (!theRequest.getParameters().containsKey(Constants.PARAM_SORT_DESC)) {
|
||||
|
|
|
@ -97,7 +97,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||
if (theRequest.getRequestType() != RequestTypeEnum.POST) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
|
||||
/*
|
||||
* We are being a bit lenient here, since technically the client is supposed to include the version in the
|
||||
* Content-Location header, but we allow it in the PUT URL as well..
|
||||
|
@ -122,7 +122,7 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
}
|
||||
|
||||
/*
|
||||
* @Override public boolean incomingServerRequestMatchesMethod(Request theRequest) { if
|
||||
* @Override public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) { if
|
||||
* (super.incomingServerRequestMatchesMethod(theRequest)) { if (myVersionIdParameterIndex != null) { if
|
||||
* (theRequest.getVersionId() == null) { return false; } } else { if (theRequest.getVersionId() != null) { return
|
||||
* false; } } return true; } else { return false; } }
|
||||
|
|
|
@ -34,11 +34,11 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
|||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class ValidateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
public class ValidateMethodBindingDstu1 extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
public ValidateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
public ValidateMethodBindingDstu1(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(theMethod, theContext, Validate.class, theProvider);
|
||||
|
||||
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod);
|
||||
|
@ -55,7 +55,7 @@ public class ValidateMethodBinding extends BaseOutcomeReturningMethodBindingWith
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
|
||||
if (myIdParameterIndex != null) {
|
||||
theParams[myIdParameterIndex] = theRequest.getId();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
public class ValidateMethodBindingDstu2 extends OperationMethodBinding {
|
||||
|
||||
public ValidateMethodBindingDstu2(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Validate theAnnotation) {
|
||||
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type());
|
||||
|
||||
List<IParameter> newParams = new ArrayList<IParameter>();
|
||||
int idx = 0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof ResourceParameter) {
|
||||
if (IBaseResource.class.isAssignableFrom(((ResourceParameter) next).getResourceType())) {
|
||||
Class<?> parameterType = theMethod.getParameterTypes()[idx];
|
||||
if (String.class.equals(parameterType) || EncodingEnum.class.equals(parameterType)) {
|
||||
newParams.add(next);
|
||||
} else {
|
||||
OperationParameter parameter = new OperationParameter(Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_RESOURCE);
|
||||
parameter.initializeTypes(theMethod, null, null, parameterType);
|
||||
newParams.add(parameter);
|
||||
}
|
||||
} else {
|
||||
newParams.add(next);
|
||||
}
|
||||
} else {
|
||||
newParams.add(next);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
setParameters(newParams);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -34,7 +34,6 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
|
@ -130,7 +129,7 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
List<QualifiedParamList> paramList = new ArrayList<QualifiedParamList>();
|
||||
String name = getName();
|
||||
|
|
|
@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.param;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -49,8 +50,7 @@ import ca.uhn.fhir.parser.IParser;
|
|||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter.Mode;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
@ -103,7 +103,7 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
switch (myMode) {
|
||||
case BODY:
|
||||
try {
|
||||
|
@ -138,11 +138,11 @@ public class ResourceParameter implements IParameter {
|
|||
return requestReader;
|
||||
}
|
||||
|
||||
static Reader createRequestReader(Request theRequest, byte[] theRequestContents) {
|
||||
static Reader createRequestReader(RequestDetails theRequest, byte[] theRequestContents) {
|
||||
return createRequestReader(theRequestContents, determineRequestCharset(theRequest));
|
||||
}
|
||||
|
||||
static Charset determineRequestCharset(Request theRequest) {
|
||||
static Charset determineRequestCharset(RequestDetails theRequest) {
|
||||
String ct = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
||||
Charset charset = null;
|
||||
|
@ -156,7 +156,7 @@ public class ResourceParameter implements IParameter {
|
|||
return charset;
|
||||
}
|
||||
|
||||
public static IBaseResource loadResourceFromRequest(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||
public static IBaseResource loadResourceFromRequest(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding, Class<? extends IBaseResource> theResourceType) {
|
||||
FhirContext ctx = theRequest.getServer().getFhirContext();
|
||||
|
||||
final Charset charset = determineRequestCharset(theRequest);
|
||||
|
|
|
@ -40,7 +40,7 @@ import ca.uhn.fhir.parser.IParser;
|
|||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -98,7 +98,7 @@ public class TransactionParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
|
||||
// TODO: don't use a default encoding, just fail!
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
|
|
|
@ -43,6 +43,7 @@ public class Constants {
|
|||
public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + "; charset=UTF-8";
|
||||
public static final String CT_XML = "application/xml";
|
||||
public static final String ENCODING_GZIP = "gzip";
|
||||
public static final String EXTOP_VALIDATE = "$validate";
|
||||
public static final String FORMAT_JSON = "json";
|
||||
public static final Set<String> FORMAT_VAL_JSON;
|
||||
public static final Map<String, EncodingEnum> FORMAT_VAL_TO_ENCODING;
|
||||
|
@ -91,13 +92,13 @@ public class Constants {
|
|||
public static final String PARAM_FORMAT = "_format";
|
||||
public static final String PARAM_HISTORY = "_history";
|
||||
public static final String PARAM_INCLUDE = "_include";
|
||||
public static final String PARAM_REVINCLUDE = "_revinclude";
|
||||
public static final String PARAM_NARRATIVE = "_narrative";
|
||||
public static final String PARAM_PAGINGACTION = "_getpages";
|
||||
public static final String PARAM_PAGINGOFFSET = "_getpagesoffset";
|
||||
public static final String PARAM_PRETTY = "_pretty";
|
||||
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
|
||||
public static final String PARAM_QUERY = "_query";
|
||||
public static final String PARAM_REVINCLUDE = "_revinclude";
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String PARAM_SINCE = "_since";
|
||||
public static final String PARAM_SORT = "_sort";
|
||||
|
@ -106,6 +107,8 @@ public class Constants {
|
|||
public static final String PARAM_TAGS = "_tags";
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
public static final String PARAMQUALIFIER_MISSING = ":missing";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
|
||||
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
|
||||
public static final String PARAMQUALIFIER_TOKEN_TEXT = ":text";
|
||||
public static final int STATUS_HTTP_200_OK = 200;
|
||||
|
@ -125,8 +128,9 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
public static final String EXTOP_VALIDATE_MODE = "mode";
|
||||
public static final String EXTOP_VALIDATE_PROFILE = "profile";
|
||||
public static final String EXTOP_VALIDATE_RESOURCE = "resource";
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
|
@ -44,7 +44,7 @@ public class ResourceBinding {
|
|||
this.methods = methods;
|
||||
}
|
||||
|
||||
public BaseMethodBinding<?> getMethod(Request theRequest) throws Exception {
|
||||
public BaseMethodBinding<?> getMethod(RequestDetails theRequest) {
|
||||
if (null == methods) {
|
||||
ourLog.warn("No methods exist for resource: {}", resourceName);
|
||||
return null;
|
||||
|
|
|
@ -27,7 +27,16 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
|
@ -37,17 +46,13 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.ProvidedResourceScanner;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Destroy;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
|
@ -55,11 +60,9 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
|||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.OtherOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||
|
@ -426,7 +429,7 @@ public class RestfulServer extends HttpServlet {
|
|||
return myServerVersion;
|
||||
}
|
||||
|
||||
private void handlePagingRequest(Request theRequest, HttpServletResponse theResponse, String thePagingAction) throws IOException {
|
||||
private void handlePagingRequest(RequestDetails theRequest, HttpServletResponse theResponse, String thePagingAction) throws IOException {
|
||||
IBundleProvider resultList = getPagingProvider().retrieveResultList(thePagingAction);
|
||||
if (resultList == null) {
|
||||
ourLog.info("Client requested unknown paging ID[{}]", thePagingAction);
|
||||
|
@ -496,7 +499,7 @@ public class RestfulServer extends HttpServlet {
|
|||
return;
|
||||
}
|
||||
}
|
||||
RestfulServerUtils.streamResponseAsResource(this, theResponse, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), false);
|
||||
RestfulServerUtils.streamResponseAsResource(this, theResponse, resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +514,7 @@ public class RestfulServer extends HttpServlet {
|
|||
|
||||
String fhirServerBase = null;
|
||||
boolean requestIsBrowser = requestIsBrowser(theRequest);
|
||||
Request requestDetails = new Request();
|
||||
RequestDetails requestDetails = new RequestDetails();
|
||||
requestDetails.setServer(this);
|
||||
|
||||
try {
|
||||
|
@ -816,6 +819,7 @@ public class RestfulServer extends HttpServlet {
|
|||
* (which extends {@link ServletException}), as this is a flag to the servlet container that the servlet
|
||||
* is not usable.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected void initialize() throws ServletException {
|
||||
// nothing by default
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
@ -55,24 +55,264 @@ import ca.uhn.fhir.model.api.Tag;
|
|||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
public class RestfulServerUtils {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
|
||||
|
||||
static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||
String countString = theRequest.getParameter(name);
|
||||
Integer count = null;
|
||||
if (isNotBlank(countString)) {
|
||||
try {
|
||||
count = Integer.parseInt(countString);
|
||||
} catch (NumberFormatException e) {
|
||||
ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
||||
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
|
||||
if (theResource instanceof IResource) {
|
||||
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
|
||||
if (tl == null) {
|
||||
tl = new TagList();
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
||||
String profile = nextDef.getResourceProfile(theServerBase);
|
||||
if (isNotBlank(profile)) {
|
||||
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
|
||||
try {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theServerBase);
|
||||
b.append('?');
|
||||
b.append(Constants.PARAM_PAGINGACTION);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(theSearchId, "UTF-8"));
|
||||
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PAGINGOFFSET);
|
||||
b.append('=');
|
||||
b.append(theOffset);
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_COUNT);
|
||||
b.append('=');
|
||||
b.append(theCount);
|
||||
if (theResponseEncoding != null) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_FORMAT);
|
||||
b.append('=');
|
||||
b.append(theResponseEncoding.getRequestContentType());
|
||||
}
|
||||
if (thePrettyPrint) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PRETTY);
|
||||
b.append('=');
|
||||
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
|
||||
}
|
||||
|
||||
if (theIncludes != null) {
|
||||
for (Include nextInclude : theIncludes) {
|
||||
if (isNotBlank(nextInclude.getValue())) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_INCLUDE);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.toString();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 not supported", e);// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
public static RestfulServer.NarrativeModeEnum determineNarrativeMode(RequestDetails theRequest) {
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE);
|
||||
RestfulServer.NarrativeModeEnum narrativeMode = null;
|
||||
if (narrative != null && narrative.length > 0) {
|
||||
try {
|
||||
narrativeMode = RestfulServer.NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ourLog.debug("Invalid {} parameger: {}", Constants.PARAM_NARRATIVE, narrative[0]);
|
||||
narrativeMode = null;
|
||||
}
|
||||
}
|
||||
if (narrativeMode == null) {
|
||||
narrativeMode = RestfulServer.NarrativeModeEnum.NORMAL;
|
||||
}
|
||||
return narrativeMode;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncoding(RequestDetails theReq) {
|
||||
EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncodingNoDefault(RequestDetails theReq) {
|
||||
EncodingEnum retVal = null;
|
||||
Enumeration<String> acceptValues = theReq.getServletRequest().getHeaders(Constants.HEADER_CONTENT_TYPE);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements() && retVal == null) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
|
||||
for (String nextPart : nextAcceptHeaderValue.split(",")) {
|
||||
int scIdx = nextPart.indexOf(';');
|
||||
if (scIdx == 0) {
|
||||
continue;
|
||||
}
|
||||
if (scIdx != -1) {
|
||||
nextPart = nextPart.substring(0, scIdx);
|
||||
}
|
||||
nextPart = nextPart.trim();
|
||||
retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq) {
|
||||
String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
|
||||
if (format != null) {
|
||||
for (String nextFormat : format) {
|
||||
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Enumeration<String> acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements()) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
|
||||
for (String nextPart : nextAcceptHeaderValue.split(",")) {
|
||||
int scIdx = nextPart.indexOf(';');
|
||||
if (scIdx == 0) {
|
||||
continue;
|
||||
}
|
||||
if (scIdx != -1) {
|
||||
nextPart = nextPart.substring(0, scIdx);
|
||||
}
|
||||
nextPart = nextPart.trim();
|
||||
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's <code>"_format"</code> parameter and <code>"Accept:"</code> HTTP header.
|
||||
*/
|
||||
public static EncodingEnum determineResponseEncodingWithDefault(RestfulServer theServer, HttpServletRequest theReq) {
|
||||
EncodingEnum retVal = determineResponseEncodingNoDefault(theReq);
|
||||
if (retVal == null) {
|
||||
retVal = theServer.getDefaultResponseEncoding();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static Integer extractCountParameter(HttpServletRequest theRequest) {
|
||||
return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT);
|
||||
}
|
||||
|
||||
public static IParser getNewParser(FhirContext theContext, EncodingEnum theResponseEncoding, boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode) {
|
||||
IParser parser;
|
||||
switch (theResponseEncoding) {
|
||||
case JSON:
|
||||
parser = theContext.newJsonParser();
|
||||
break;
|
||||
case XML:
|
||||
default:
|
||||
parser = theContext.newXmlParser();
|
||||
break;
|
||||
}
|
||||
return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == RestfulServer.NarrativeModeEnum.SUPPRESS);
|
||||
}
|
||||
|
||||
static Writer getWriter(HttpServletResponse theHttpResponse, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
Writer writer;
|
||||
if (theRespondGzip) {
|
||||
theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
|
||||
writer = new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), "UTF-8");
|
||||
} else {
|
||||
writer = theHttpResponse.getWriter();
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] pretty = requestParams.get(Constants.PARAM_PRETTY);
|
||||
boolean prettyPrint;
|
||||
if (pretty != null && pretty.length > 0) {
|
||||
if (Constants.PARAM_PRETTY_VALUE_TRUE.equals(pretty[0])) {
|
||||
prettyPrint = true;
|
||||
} else {
|
||||
prettyPrint = false;
|
||||
}
|
||||
} else {
|
||||
prettyPrint = theServer.isDefaultPrettyPrint();
|
||||
Enumeration<String> acceptValues = theRequest.getServletRequest().getHeaders(Constants.HEADER_ACCEPT);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements()) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue.contains("pretty=true")) {
|
||||
prettyPrint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return prettyPrint;
|
||||
}
|
||||
|
||||
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, EncodingEnum theResponseEncoding, String theServerBase,
|
||||
boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, boolean theRequestIsBrowser) throws IOException {
|
||||
assert !theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
||||
EncodingEnum responseEncoding = theResponseEncoding != null ? theResponseEncoding : theServer.getDefaultResponseEncoding();
|
||||
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
theHttpResponse.setContentType(responseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
|
||||
theHttpResponse.setContentType(Constants.CT_HTML);
|
||||
} else {
|
||||
theHttpResponse.setContentType(responseEncoding.getBundleContentType());
|
||||
}
|
||||
|
||||
theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theHttpResponse);
|
||||
|
||||
Writer writer = RestfulServerUtils.getWriter(theHttpResponse, theRespondGzip);
|
||||
try {
|
||||
if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
|
||||
for (IResource next : bundle.toListOfResources()) {
|
||||
writer.append(next.getText().getDiv().getValueAsString());
|
||||
writer.append("<hr/>");
|
||||
}
|
||||
} else {
|
||||
IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), responseEncoding, thePrettyPrint, theNarrativeMode);
|
||||
parser.setServerBaseUrl(theServerBase);
|
||||
parser.encodeBundleToWriter(bundle, writer);
|
||||
}
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
|
||||
|
@ -168,258 +408,17 @@ public class RestfulServerUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] pretty = requestParams.get(Constants.PARAM_PRETTY);
|
||||
boolean prettyPrint;
|
||||
if (pretty != null && pretty.length > 0) {
|
||||
if (Constants.PARAM_PRETTY_VALUE_TRUE.equals(pretty[0])) {
|
||||
prettyPrint = true;
|
||||
} else {
|
||||
prettyPrint = false;
|
||||
}
|
||||
} else {
|
||||
prettyPrint = theServer.isDefaultPrettyPrint();
|
||||
Enumeration<String> acceptValues = ((Request)theRequest).getServletRequest().getHeaders(Constants.HEADER_ACCEPT);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements()) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue.contains("pretty=true")) {
|
||||
prettyPrint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return prettyPrint;
|
||||
}
|
||||
|
||||
static Writer getWriter(HttpServletResponse theHttpResponse, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
Writer writer;
|
||||
if (theRespondGzip) {
|
||||
theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
|
||||
writer = new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), "UTF-8");
|
||||
} else {
|
||||
writer = theHttpResponse.getWriter();
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncoding(Request theReq) {
|
||||
EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncodingNoDefault(Request theReq) {
|
||||
EncodingEnum retVal = null;
|
||||
Enumeration<String> acceptValues = theReq.getServletRequest().getHeaders(Constants.HEADER_CONTENT_TYPE);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements() && retVal == null) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
|
||||
for (String nextPart : nextAcceptHeaderValue.split(",")) {
|
||||
int scIdx = nextPart.indexOf(';');
|
||||
if (scIdx == 0) {
|
||||
continue;
|
||||
}
|
||||
if (scIdx != -1) {
|
||||
nextPart = nextPart.substring(0, scIdx);
|
||||
}
|
||||
nextPart = nextPart.trim();
|
||||
retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
|
||||
try {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theServerBase);
|
||||
b.append('?');
|
||||
b.append(Constants.PARAM_PAGINGACTION);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(theSearchId, "UTF-8"));
|
||||
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PAGINGOFFSET);
|
||||
b.append('=');
|
||||
b.append(theOffset);
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_COUNT);
|
||||
b.append('=');
|
||||
b.append(theCount);
|
||||
if (theResponseEncoding != null) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_FORMAT);
|
||||
b.append('=');
|
||||
b.append(theResponseEncoding.getRequestContentType());
|
||||
}
|
||||
if (thePrettyPrint) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_PRETTY);
|
||||
b.append('=');
|
||||
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
|
||||
}
|
||||
|
||||
if (theIncludes != null) {
|
||||
for (Include nextInclude : theIncludes) {
|
||||
if (isNotBlank(nextInclude.getValue())) {
|
||||
b.append('&');
|
||||
b.append(Constants.PARAM_INCLUDE);
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.toString();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 not supported", e);// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
public static void addProfileToBundleEntry(FhirContext theContext, IBaseResource theResource, String theServerBase) {
|
||||
if (theResource instanceof IResource) {
|
||||
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) theResource);
|
||||
if (tl == null) {
|
||||
tl = new TagList();
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) theResource, tl);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(theResource);
|
||||
String profile = nextDef.getResourceProfile(theServerBase);
|
||||
if (isNotBlank(profile)) {
|
||||
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static RestfulServer.NarrativeModeEnum determineNarrativeMode(RequestDetails theRequest) {
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE);
|
||||
RestfulServer.NarrativeModeEnum narrativeMode = null;
|
||||
if (narrative != null && narrative.length > 0) {
|
||||
static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||
String countString = theRequest.getParameter(name);
|
||||
Integer count = null;
|
||||
if (isNotBlank(countString)) {
|
||||
try {
|
||||
narrativeMode = RestfulServer.NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ourLog.debug("Invalid {} parameger: {}", Constants.PARAM_NARRATIVE, narrative[0]);
|
||||
narrativeMode = null;
|
||||
count = Integer.parseInt(countString);
|
||||
} catch (NumberFormatException e) {
|
||||
ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
||||
}
|
||||
}
|
||||
if (narrativeMode == null) {
|
||||
narrativeMode = RestfulServer.NarrativeModeEnum.NORMAL;
|
||||
}
|
||||
return narrativeMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's <code>"_format"</code> parameter and <code>"Accept:"</code> HTTP header.
|
||||
*/
|
||||
public static EncodingEnum determineResponseEncodingWithDefault(RestfulServer theServer, HttpServletRequest theReq) {
|
||||
EncodingEnum retVal = determineResponseEncodingNoDefault(theReq);
|
||||
if (retVal == null) {
|
||||
retVal = theServer.getDefaultResponseEncoding();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static IParser getNewParser(FhirContext theContext, EncodingEnum theResponseEncoding, boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode) {
|
||||
IParser parser;
|
||||
switch (theResponseEncoding) {
|
||||
case JSON:
|
||||
parser = theContext.newJsonParser();
|
||||
break;
|
||||
case XML:
|
||||
default:
|
||||
parser = theContext.newXmlParser();
|
||||
break;
|
||||
}
|
||||
return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == RestfulServer.NarrativeModeEnum.SUPPRESS);
|
||||
}
|
||||
|
||||
public static EncodingEnum determineResponseEncodingNoDefault(HttpServletRequest theReq) {
|
||||
String[] format = theReq.getParameterValues(Constants.PARAM_FORMAT);
|
||||
if (format != null) {
|
||||
for (String nextFormat : format) {
|
||||
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Enumeration<String> acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements()) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
|
||||
for (String nextPart : nextAcceptHeaderValue.split(",")) {
|
||||
int scIdx = nextPart.indexOf(';');
|
||||
if (scIdx == 0) {
|
||||
continue;
|
||||
}
|
||||
if (scIdx != -1) {
|
||||
nextPart = nextPart.substring(0, scIdx);
|
||||
}
|
||||
nextPart = nextPart.trim();
|
||||
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Integer extractCountParameter(HttpServletRequest theRequest) {
|
||||
return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT);
|
||||
}
|
||||
|
||||
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, EncodingEnum theResponseEncoding, String theServerBase,
|
||||
boolean thePrettyPrint, RestfulServer.NarrativeModeEnum theNarrativeMode, boolean theRespondGzip, boolean theRequestIsBrowser) throws IOException {
|
||||
assert !theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
||||
EncodingEnum responseEncoding = theResponseEncoding != null ? theResponseEncoding : theServer.getDefaultResponseEncoding();
|
||||
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
theHttpResponse.setContentType(responseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
|
||||
theHttpResponse.setContentType(Constants.CT_HTML);
|
||||
} else {
|
||||
theHttpResponse.setContentType(responseEncoding.getBundleContentType());
|
||||
}
|
||||
|
||||
theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theHttpResponse);
|
||||
|
||||
Writer writer = RestfulServerUtils.getWriter(theHttpResponse, theRespondGzip);
|
||||
try {
|
||||
if (theNarrativeMode == RestfulServer.NarrativeModeEnum.ONLY) {
|
||||
for (IResource next : bundle.toListOfResources()) {
|
||||
writer.append(next.getText().getDiv().getValueAsString());
|
||||
writer.append("<hr/>");
|
||||
}
|
||||
} else {
|
||||
IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), responseEncoding, thePrettyPrint, theNarrativeMode);
|
||||
parser.setServerBaseUrl(theServerBase);
|
||||
parser.encodeBundleToWriter(bundle, writer);
|
||||
}
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint,
|
||||
|
|
|
@ -38,6 +38,8 @@ import ca.uhn.fhir.rest.param.StringAndListParam;
|
|||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.UriAndListParam;
|
||||
import ca.uhn.fhir.rest.param.UriOrListParam;
|
||||
|
||||
public class SearchParameterMap extends LinkedHashMap<String, BaseAndListParam<?>> {
|
||||
|
||||
|
@ -71,10 +73,19 @@ public class SearchParameterMap extends LinkedHashMap<String, BaseAndListParam<?
|
|||
andList.addValue(theOrListParam);
|
||||
}
|
||||
|
||||
public void add(String theName, TokenOrListParam theOrListParam) {
|
||||
TokenAndListParam andList = (TokenAndListParam) get(theName);
|
||||
public void add(String theName, QuantityOrListParam theOrListParam) {
|
||||
QuantityAndListParam andList = (QuantityAndListParam) get(theName);
|
||||
if (andList == null) {
|
||||
andList = new TokenAndListParam();
|
||||
andList = new QuantityAndListParam();
|
||||
put(theName, andList);
|
||||
}
|
||||
andList.addValue(theOrListParam);
|
||||
}
|
||||
|
||||
public void add(String theName, ReferenceOrListParam theOrListParam) {
|
||||
ReferenceAndListParam andList = (ReferenceAndListParam) get(theName);
|
||||
if (andList == null) {
|
||||
andList = new ReferenceAndListParam();
|
||||
put(theName, andList);
|
||||
}
|
||||
andList.addValue(theOrListParam);
|
||||
|
@ -89,19 +100,19 @@ public class SearchParameterMap extends LinkedHashMap<String, BaseAndListParam<?
|
|||
andList.addValue(theOrListParam);
|
||||
}
|
||||
|
||||
public void add(String theName, QuantityOrListParam theOrListParam) {
|
||||
QuantityAndListParam andList = (QuantityAndListParam) get(theName);
|
||||
public void add(String theName, TokenOrListParam theOrListParam) {
|
||||
TokenAndListParam andList = (TokenAndListParam) get(theName);
|
||||
if (andList == null) {
|
||||
andList = new QuantityAndListParam();
|
||||
andList = new TokenAndListParam();
|
||||
put(theName, andList);
|
||||
}
|
||||
andList.addValue(theOrListParam);
|
||||
}
|
||||
|
||||
public void add(String theName, ReferenceOrListParam theOrListParam) {
|
||||
ReferenceAndListParam andList = (ReferenceAndListParam) get(theName);
|
||||
public void add(String theName, UriOrListParam theOrListParam) {
|
||||
UriAndListParam andList = (UriAndListParam) get(theName);
|
||||
if (andList == null) {
|
||||
andList = new ReferenceAndListParam();
|
||||
andList = new UriAndListParam();
|
||||
put(theName, andList);
|
||||
}
|
||||
andList.addValue(theOrListParam);
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
@ -127,7 +126,7 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
|||
}
|
||||
|
||||
boolean requestIsBrowser = RestfulServer.requestIsBrowser(theRequest);
|
||||
String fhirServerBase = ((Request) theRequestDetails).getFhirServerBase();
|
||||
String fhirServerBase = theRequestDetails.getFhirServerBase();
|
||||
RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), theResponse, oo, RestfulServerUtils.determineResponseEncodingNoDefault(theRequest), true, requestIsBrowser,
|
||||
NarrativeModeEnum.NORMAL, statusCode, false, fhirServerBase, false);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
|
||||
/**
|
||||
|
@ -52,8 +54,12 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
* <td>The resource ID associated with this request, or the resource name if the request applies to a type but not an instance, or "" otherwise</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${operationName}</td>
|
||||
* <td>If the request is an extended operation (e.g. "$validate") this value will be the operation name, or "" otherwise</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${operationType}</td>
|
||||
* <td>A code indicating the operation type for this request, e.g. "read", "history-instance", etc.)</td>
|
||||
* <td>A code indicating the operation type for this request, e.g. "read", "history-instance", "extended-operation-instance", etc.)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${remoteAddr}</td>
|
||||
|
@ -69,6 +75,10 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
* <td>The HTTP request parameters (or "")</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${responseEncodingNoDefault}</td>
|
||||
* <td>The encoding format requested by the client via the _format parameter or the Accept header. Value will be "json" or "xml", or "" if the client did not explicitly request a format</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${servletPath}</td>
|
||||
* <td>The part of thre requesting URL that corresponds to the particular Servlet being called (see {@link HttpServletRequest#getServletPath()})</td>
|
||||
* </tr>
|
||||
|
@ -125,6 +135,11 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||
|
||||
@Override
|
||||
public String lookup(String theKey) {
|
||||
|
||||
/*
|
||||
* TODO: this method could be made more efficient through some sort of lookup map
|
||||
*/
|
||||
|
||||
if ("operationType".equals(theKey)) {
|
||||
if (myRequestDetails.getResourceOperationType() != null) {
|
||||
return myRequestDetails.getResourceOperationType().getCode();
|
||||
|
@ -136,6 +151,19 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||
return myRequestDetails.getOtherOperationType().getCode();
|
||||
}
|
||||
return "";
|
||||
} else if ("operationName".equals(theKey)) {
|
||||
if (myRequestDetails.getOtherOperationType() != null) {
|
||||
switch (myRequestDetails.getOtherOperationType()) {
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
return myRequestDetails.getOperation();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else if ("id".equals(theKey)) {
|
||||
if (myRequestDetails.getId() != null) {
|
||||
return myRequestDetails.getId().getValue();
|
||||
|
@ -175,7 +203,15 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||
return StringUtils.defaultString(val);
|
||||
} else if (theKey.startsWith("remoteAddr")) {
|
||||
return StringUtils.defaultString(myRequest.getRemoteAddr());
|
||||
} else if (theKey.equals("responseEncodingNoDefault")) {
|
||||
EncodingEnum encoding = RestfulServerUtils.determineResponseEncodingNoDefault(myRequest);
|
||||
if (encoding != null) {
|
||||
return encoding.name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return "!VAL!";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.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 IBaseConformance extends IBaseResource {
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package org.hl7.fhir.instance.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 IBaseXhtml extends IPrimitiveType<String> {
|
||||
|
||||
|
|
|
@ -77,6 +77,19 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-schematron</artifactId>
|
||||
<version>${phloc_schematron_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<version>${phloc_commons_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- For UCUM -->
|
||||
<dependency>
|
||||
<groupId>org.jscience</groupId>
|
||||
|
|
|
@ -24,9 +24,16 @@ import javax.servlet.http.HttpServletRequest;
|
|||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome.Issue;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.parser.IParserErrorHandler;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
|
@ -35,8 +42,14 @@ import ca.uhn.fhir.rest.annotation.Operation;
|
|||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
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.ValidationResult;
|
||||
|
||||
public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResourceProvider<T> {
|
||||
|
||||
|
@ -78,25 +91,6 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
}
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId, @ConditionalUrlParam String theConditional) {
|
||||
startRequest(theRequest);
|
||||
try {
|
||||
if (theConditional != null) {
|
||||
return getDao().update(theResource, theConditional);
|
||||
} else {
|
||||
theResource.setId(theId);
|
||||
return getDao().update(theResource);
|
||||
}
|
||||
} catch (ResourceNotFoundException e) {
|
||||
ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
|
||||
theResource.setId(theId);
|
||||
return getDao().create(theResource);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
}
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
@Operation(name="$meta", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=MetaDt.class)
|
||||
|
@ -141,4 +135,67 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
return parameters;
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId, @ConditionalUrlParam String theConditional) {
|
||||
startRequest(theRequest);
|
||||
try {
|
||||
if (theConditional != null) {
|
||||
return getDao().update(theResource, theConditional);
|
||||
} else {
|
||||
theResource.setId(theId);
|
||||
return getDao().update(theResource);
|
||||
}
|
||||
} catch (ResourceNotFoundException e) {
|
||||
ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
|
||||
theResource.setId(theId);
|
||||
return getDao().create(theResource);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@Validate
|
||||
public MethodOutcome validate(@ResourceParam T theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
|
||||
@Validate.Profile String theProfile) {
|
||||
|
||||
final OperationOutcome oo = new OperationOutcome();
|
||||
|
||||
IParser parser = theEncoding.newParser(getContext());
|
||||
parser.setParserErrorHandler(new IParserErrorHandler() {
|
||||
|
||||
@Override
|
||||
public void unknownAttribute(IParseLocation theLocation, String theAttributeName) {
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown attribute found: " + theAttributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unknownElement(IParseLocation theLocation, String theElementName) {
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDetails("Unknown element found: " + theElementName);
|
||||
}
|
||||
});
|
||||
|
||||
FhirValidator validator = getContext().newValidator();
|
||||
validator.setValidateAgainstStandardSchema(true);
|
||||
validator.setValidateAgainstStandardSchematron(true);
|
||||
ValidationResult result = validator.validateWithResult(theResource);
|
||||
for (BaseIssue next : result.getOperationOutcome().getIssue()) {
|
||||
oo.getIssue().add((Issue) next);
|
||||
}
|
||||
|
||||
if (oo.getIssue().size() > 0) {
|
||||
/*
|
||||
* It is also possible to pass an OperationOutcome resource to the UnprocessableEntityException if you want to return a custom populated OperationOutcome. Otherwise, a simple one is
|
||||
* created using the string supplied below.
|
||||
*/
|
||||
throw new UnprocessableEntityException("Validation failed", oo);
|
||||
}
|
||||
|
||||
// This method returns a MethodOutcome object
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Validation succeeded");
|
||||
retVal.setOperationOutcome(oo);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
@ -69,6 +70,7 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|||
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
|
@ -91,59 +93,57 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
private static ClassPathXmlApplicationContext ourAppCtx;
|
||||
private static IGenericClient ourClient;
|
||||
private static DaoConfig ourDaoConfig;
|
||||
private static FhirContext ourFhirCtx;
|
||||
private static CloseableHttpClient ourHttpClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
|
||||
private static IFhirResourceDao<Organization> ourOrganizationDao;
|
||||
private static int ourPort;
|
||||
// private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
// private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
// private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
|
||||
private static Server ourServer;
|
||||
private static IFhirResourceDao<Organization> ourOrganizationDao;
|
||||
private static DaoConfig ourDaoConfig;
|
||||
private static CloseableHttpClient ourHttpClient;
|
||||
private static String ourServerBase;
|
||||
private static int ourPort;
|
||||
|
||||
// private static JpaConformanceProvider ourConfProvider;
|
||||
|
||||
/**
|
||||
* Test for issue #60
|
||||
*/
|
||||
@Test
|
||||
public void testStoreUtf8Characters() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.setName("測試醫院");
|
||||
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
||||
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
// Read back directly from the DAO
|
||||
{
|
||||
Organization returned = ourOrganizationDao.read(orgId);
|
||||
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
|
||||
ourLog.info(val);
|
||||
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
|
||||
private void delete(String theResourceType, String theParamName, String theParamValue) {
|
||||
Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
|
||||
for (IResource next : resources.toListOfResources()) {
|
||||
ourLog.info("Deleting resource: {}", next.getId());
|
||||
ourClient.delete().resource(next).execute();
|
||||
}
|
||||
// Read back through the HTTP API
|
||||
{
|
||||
Organization returned = ourClient.read(Organization.class, orgId);
|
||||
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
|
||||
ourLog.info(val);
|
||||
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
|
||||
}
|
||||
|
||||
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
|
||||
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
|
||||
for (IResource next : resources.toListOfResources()) {
|
||||
ourLog.info("Deleting resource: {}", next.getId());
|
||||
ourClient.delete().resource(next).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResourceWithNumericId() throws IOException {
|
||||
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||
public void testCountParam() throws Exception {
|
||||
// NB this does not get used- The paging provider has its own limits built in
|
||||
ourDaoConfig.setHardSearchLimit(100);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
response.close();
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("rpdstu2_testCountParam_01");
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(10).execute();
|
||||
assertEquals(100, found.getTotalResults().getValue().intValue());
|
||||
assertEquals(10, found.getEntries().size());
|
||||
|
||||
found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(999).execute();
|
||||
assertEquals(100, found.getTotalResults().getValue().intValue());
|
||||
assertEquals(50, found.getEntries().size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -183,37 +183,56 @@ public class ResourceProviderDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateResourceConditional() throws IOException {
|
||||
String methodName = "testUpdateResourceConditional";
|
||||
public void testCreateResourceWithNumericId() throws IOException {
|
||||
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdDt id;
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
response = ourHttpClient.execute(put);
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
IdDt newId = new IdDt(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue());
|
||||
assertEquals(id.toVersionless(), newId.toVersionless()); // version shouldn't match for conditional update
|
||||
assertNotEquals(id, newId);
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeepChaining() {
|
||||
delete("Location", Location.SP_NAME, "testDeepChainingL1");
|
||||
delete("Location", Location.SP_NAME, "testDeepChainingL2");
|
||||
deleteToken("Encounter", Encounter.SP_IDENTIFIER, "urn:foo", "testDeepChainingE1");
|
||||
|
||||
Location l1 = new Location();
|
||||
l1.getNameElement().setValue("testDeepChainingL1");
|
||||
IdDt l1id = ourClient.create().resource(l1).execute().getId();
|
||||
|
||||
Location l2 = new Location();
|
||||
l2.getNameElement().setValue("testDeepChainingL2");
|
||||
l2.getPartOf().setReference(l1id.toVersionless().toUnqualified());
|
||||
IdDt l2id = ourClient.create().resource(l2).execute().getId();
|
||||
|
||||
Encounter e1 = new Encounter();
|
||||
e1.addIdentifier().setSystem("urn:foo").setValue("testDeepChainingE1");
|
||||
e1.getStatusElement().setValueAsEnum(EncounterStateEnum.IN_PROGRESS);
|
||||
e1.getClassElementElement().setValueAsEnum(EncounterClassEnum.HOME);
|
||||
ca.uhn.fhir.model.dstu2.resource.Encounter.Location location = e1.addLocation();
|
||||
location.getLocation().setReference(l2id.toUnqualifiedVersionless());
|
||||
location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date()));
|
||||
IdDt e1id = ourClient.create().resource(e1).execute().getId();
|
||||
|
||||
//@formatter:off
|
||||
Bundle res = ourClient.search()
|
||||
.forResource(Encounter.class)
|
||||
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
|
||||
.include(Encounter.INCLUDE_LOCATION)
|
||||
.include(Location.INCLUDE_PARTOF)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(3, res.size());
|
||||
assertEquals(1, res.getResources(Encounter.class).size());
|
||||
assertEquals(e1id.toUnqualifiedVersionless(), res.getResources(Encounter.class).get(0).getId().toUnqualifiedVersionless());
|
||||
|
||||
}
|
||||
|
||||
|
@ -325,184 +344,62 @@ public class ResourceProviderDstu2Test {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test for issue #60
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testReadAllInstancesOfType() throws Exception {
|
||||
Patient pat;
|
||||
public void testDiagnosticOrderResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
||||
|
||||
pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02");
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
DiagnosticOrder res = new DiagnosticOrder();
|
||||
res.addIdentifier().setSystem("urn:foo").setValue("123");
|
||||
|
||||
client.create().resource(res).execute();
|
||||
|
||||
int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
{
|
||||
Bundle returned = ourClient.search().forResource(Patient.class).encodedXml().execute();
|
||||
assertThat(returned.size(), greaterThan(1));
|
||||
assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum());
|
||||
}
|
||||
{
|
||||
Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute();
|
||||
assertThat(returned.size(), greaterThan(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testSearchBundleDoesntIncludeTextElement() throws Exception {
|
||||
HttpGet read = new HttpGet(ourServerBase + "/Patient?_format=json");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(read);
|
||||
try {
|
||||
String text = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(text);
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatusLine().getStatusCode());
|
||||
assertThat(text, not(containsString("\"text\",\"type\"")));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
public void testDocumentManifestResources() throws Exception {
|
||||
ourFhirCtx.getResourceDefinition(Practitioner.class);
|
||||
ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
|
||||
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
|
||||
|
||||
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"));
|
||||
client.create().resource(resBody).execute();
|
||||
|
||||
int newSize = client.search().forResource(DocumentManifest.class).execute().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testSearchWithInclude() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
|
||||
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||
public void testDocumentReferenceResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude02");
|
||||
pat.getManagingOrganization().setReference(orgId);
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
int initialSize = client.search().forResource(DocumentReference.class).execute().size();
|
||||
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
|
||||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"));
|
||||
client.create().resource(resBody).execute();
|
||||
|
||||
assertEquals(2, found.size());
|
||||
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString("<table class=\"hapiPropertyTable"));
|
||||
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
int newSize = client.search().forResource(DocumentReference.class).execute().size();
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissing() throws Exception {
|
||||
ourLog.info("Starting testSearchWithMissing");
|
||||
String methodName = "testSearchWithMissing";
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName(methodName + "_0" + i);
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
org.setName(methodName + "name");
|
||||
IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(false))
|
||||
.limitTo(100)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + ": " + list.toString());
|
||||
assertThat("Wanted " + orgNotMissing + " but got: " + list, list, containsInRelativeOrder(orgNotMissing));
|
||||
assertThat(list, not(containsInRelativeOrder(orgMissing)));
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(true))
|
||||
.limitTo(100)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
|
||||
assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
|
||||
assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
|
||||
}
|
||||
|
||||
private List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {
|
||||
List<IdDt> list = new ArrayList<IdDt>();
|
||||
for (BundleEntry next : found.getEntries()) {
|
||||
list.add(next.getResource().getId().toUnqualifiedVersionless());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverythingOperation() throws Exception {
|
||||
String methodName = "testEverythingOperation";
|
||||
|
||||
Organization org1 = new Organization();
|
||||
org1.setName(methodName + "1");
|
||||
IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily(methodName);
|
||||
p.getManagingOrganization().setReference(orgId1);
|
||||
IdDt patientId = ourClient.create().resource(p).execute().getId();
|
||||
|
||||
Organization org2 = new Organization();
|
||||
org2.setName(methodName + "1");
|
||||
IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
|
||||
|
||||
Device dev = new Device();
|
||||
dev.setModel(methodName);
|
||||
dev.getOwner().setReference(orgId2);
|
||||
IdDt devId = ourClient.create().resource(dev).execute().getId();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getSubject().setReference(patientId);
|
||||
obs.getDevice().setReference(devId);
|
||||
IdDt obsId = ourClient.create().resource(obs).execute().getId();
|
||||
|
||||
Encounter enc = new Encounter();
|
||||
enc.getPatient().setReference(patientId);
|
||||
IdDt encId = ourClient.create().resource(enc).execute().getId();
|
||||
|
||||
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||
|
||||
Set<IdDt> ids = new HashSet<IdDt>();
|
||||
for (Entry next : b.getEntry()) {
|
||||
ids.add(next.getResource().getId());
|
||||
}
|
||||
|
||||
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
|
||||
|
||||
// _revinclude's are counted but not _include's
|
||||
assertEquals(3, b.getTotal().intValue());
|
||||
|
||||
ourLog.info(ids.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -603,26 +500,50 @@ public class ResourceProviderDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCountParam() throws Exception {
|
||||
// NB this does not get used- The paging provider has its own limits built in
|
||||
ourDaoConfig.setHardSearchLimit(100);
|
||||
public void testEverythingOperation() throws Exception {
|
||||
String methodName = "testEverythingOperation";
|
||||
|
||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName("rpdstu2_testCountParam_01");
|
||||
resources.add(org);
|
||||
Organization org1 = new Organization();
|
||||
org1.setName(methodName + "1");
|
||||
IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily(methodName);
|
||||
p.getManagingOrganization().setReference(orgId1);
|
||||
IdDt patientId = ourClient.create().resource(p).execute().getId();
|
||||
|
||||
Organization org2 = new Organization();
|
||||
org2.setName(methodName + "1");
|
||||
IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
|
||||
|
||||
Device dev = new Device();
|
||||
dev.setModel(methodName);
|
||||
dev.getOwner().setReference(orgId2);
|
||||
IdDt devId = ourClient.create().resource(dev).execute().getId();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getSubject().setReference(patientId);
|
||||
obs.getDevice().setReference(devId);
|
||||
IdDt obsId = ourClient.create().resource(obs).execute().getId();
|
||||
|
||||
Encounter enc = new Encounter();
|
||||
enc.getPatient().setReference(patientId);
|
||||
IdDt encId = ourClient.create().resource(enc).execute().getId();
|
||||
|
||||
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||
|
||||
Set<IdDt> ids = new HashSet<IdDt>();
|
||||
for (Entry next : b.getEntry()) {
|
||||
ids.add(next.getResource().getId());
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(10).execute();
|
||||
assertEquals(100, found.getTotalResults().getValue().intValue());
|
||||
assertEquals(10, found.getEntries().size());
|
||||
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
|
||||
|
||||
found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).limitTo(999).execute();
|
||||
assertEquals(100, found.getTotalResults().getValue().intValue());
|
||||
assertEquals(50, found.getEntries().size());
|
||||
// _revinclude's are counted but not _include's
|
||||
assertEquals(3, b.getTotal().intValue());
|
||||
|
||||
ourLog.info(ids.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -644,119 +565,31 @@ public class ResourceProviderDstu2Test {
|
|||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
* Test for issue #60
|
||||
*/
|
||||
@Test
|
||||
public void testDocumentManifestResources() throws Exception {
|
||||
ourFhirCtx.getResourceDefinition(Practitioner.class);
|
||||
ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
|
||||
public void testReadAllInstancesOfType() throws Exception {
|
||||
Patient pat;
|
||||
|
||||
IGenericClient client = ourClient;
|
||||
pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
|
||||
pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02");
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"));
|
||||
client.create().resource(resBody).execute();
|
||||
|
||||
int newSize = client.search().forResource(DocumentManifest.class).execute().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testDocumentReferenceResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
int initialSize = client.search().forResource(DocumentReference.class).execute().size();
|
||||
|
||||
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"));
|
||||
client.create().resource(resBody).execute();
|
||||
|
||||
int newSize = client.search().forResource(DocumentReference.class).execute().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #52
|
||||
*/
|
||||
@Test
|
||||
public void testDiagnosticOrderResources() throws Exception {
|
||||
IGenericClient client = ourClient;
|
||||
|
||||
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
||||
|
||||
DiagnosticOrder res = new DiagnosticOrder();
|
||||
res.addIdentifier().setSystem("urn:foo").setValue("123");
|
||||
|
||||
client.create().resource(res).execute();
|
||||
|
||||
int newSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
||||
|
||||
assertEquals(1, newSize - initialSize);
|
||||
|
||||
}
|
||||
|
||||
private void delete(String theResourceType, String theParamName, String theParamValue) {
|
||||
Bundle resources = ourClient.search().forResource(theResourceType).where(new StringClientParam(theParamName).matches().value(theParamValue)).execute();
|
||||
for (IResource next : resources.toListOfResources()) {
|
||||
ourLog.info("Deleting resource: {}", next.getId());
|
||||
ourClient.delete().resource(next).execute();
|
||||
{
|
||||
Bundle returned = ourClient.search().forResource(Patient.class).encodedXml().execute();
|
||||
assertThat(returned.size(), greaterThan(1));
|
||||
assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum());
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
|
||||
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
|
||||
for (IResource next : resources.toListOfResources()) {
|
||||
ourLog.info("Deleting resource: {}", next.getId());
|
||||
ourClient.delete().resource(next).execute();
|
||||
{
|
||||
Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute();
|
||||
assertThat(returned.size(), greaterThan(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeepChaining() {
|
||||
delete("Location", Location.SP_NAME, "testDeepChainingL1");
|
||||
delete("Location", Location.SP_NAME, "testDeepChainingL2");
|
||||
deleteToken("Encounter", Encounter.SP_IDENTIFIER, "urn:foo", "testDeepChainingE1");
|
||||
|
||||
Location l1 = new Location();
|
||||
l1.getNameElement().setValue("testDeepChainingL1");
|
||||
IdDt l1id = ourClient.create().resource(l1).execute().getId();
|
||||
|
||||
Location l2 = new Location();
|
||||
l2.getNameElement().setValue("testDeepChainingL2");
|
||||
l2.getPartOf().setReference(l1id.toVersionless().toUnqualified());
|
||||
IdDt l2id = ourClient.create().resource(l2).execute().getId();
|
||||
|
||||
Encounter e1 = new Encounter();
|
||||
e1.addIdentifier().setSystem("urn:foo").setValue("testDeepChainingE1");
|
||||
e1.getStatusElement().setValueAsEnum(EncounterStateEnum.IN_PROGRESS);
|
||||
e1.getClassElementElement().setValueAsEnum(EncounterClassEnum.HOME);
|
||||
ca.uhn.fhir.model.dstu2.resource.Encounter.Location location = e1.addLocation();
|
||||
location.getLocation().setReference(l2id.toUnqualifiedVersionless());
|
||||
location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date()));
|
||||
IdDt e1id = ourClient.create().resource(e1).execute().getId();
|
||||
|
||||
//@formatter:off
|
||||
Bundle res = ourClient.search()
|
||||
.forResource(Encounter.class)
|
||||
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
|
||||
.include(Encounter.INCLUDE_LOCATION)
|
||||
.include(Location.INCLUDE_PARTOF)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(3, res.size());
|
||||
assertEquals(1, res.getResources(Encounter.class).size());
|
||||
assertEquals(e1id.toUnqualifiedVersionless(), res.getResources(Encounter.class).get(0).getId().toUnqualifiedVersionless());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveAndRetrieveExistingNarrative() {
|
||||
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSaveAndRetrieveExistingNarrative01");
|
||||
|
@ -804,6 +637,20 @@ public class ResourceProviderDstu2Test {
|
|||
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSearchByResourceChain01</td>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchBundleDoesntIncludeTextElement() throws Exception {
|
||||
HttpGet read = new HttpGet(ourServerBase + "/Patient?_format=json");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(read);
|
||||
try {
|
||||
String text = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(text);
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatusLine().getStatusCode());
|
||||
assertThat(text, not(containsString("\"text\",\"type\"")));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByIdentifier() {
|
||||
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier01");
|
||||
|
@ -874,6 +721,118 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithInclude() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
|
||||
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude02");
|
||||
pat.getManagingOrganization().setReference(orgId);
|
||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
|
||||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(2, found.size());
|
||||
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString("<table class=\"hapiPropertyTable"));
|
||||
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissing() throws Exception {
|
||||
ourLog.info("Starting testSearchWithMissing");
|
||||
String methodName = "testSearchWithMissing";
|
||||
|
||||
List<IResource> resources = new ArrayList<IResource>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Organization org = new Organization();
|
||||
org.setName(methodName + "_0" + i);
|
||||
resources.add(org);
|
||||
}
|
||||
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
|
||||
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
org.setName(methodName + "name");
|
||||
IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(false))
|
||||
.limitTo(100)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + ": " + list.toString());
|
||||
assertThat("Wanted " + orgNotMissing + " but got: " + list, list, containsInRelativeOrder(orgNotMissing));
|
||||
assertThat(list, not(containsInRelativeOrder(orgMissing)));
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(true))
|
||||
.limitTo(100)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
|
||||
assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
|
||||
assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for issue #60
|
||||
*/
|
||||
@Test
|
||||
public void testStoreUtf8Characters() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.setName("測試醫院");
|
||||
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
||||
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||
|
||||
// Read back directly from the DAO
|
||||
{
|
||||
Organization returned = ourOrganizationDao.read(orgId);
|
||||
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
|
||||
ourLog.info(val);
|
||||
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
|
||||
}
|
||||
// Read back through the HTTP API
|
||||
{
|
||||
Organization returned = ourClient.read(Organization.class, orgId);
|
||||
String val = ourFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(returned);
|
||||
ourLog.info(val);
|
||||
assertThat(val, containsString("<name value=\"測試醫院\"/>"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryToCreateResourceWithReferenceThatDoesntExist() {
|
||||
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testTryToCreateResourceWithReferenceThatDoesntExist01");
|
||||
|
@ -919,6 +878,41 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateResourceConditional() throws IOException {
|
||||
String methodName = "testUpdateResourceConditional";
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdDt id;
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
response = ourHttpClient.execute(put);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
IdDt newId = new IdDt(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue());
|
||||
assertEquals(id.toVersionless(), newId.toVersionless()); // version shouldn't match for conditional update
|
||||
assertNotEquals(id, newId);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWithClientSuppliedIdWhichDoesntExist() {
|
||||
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2");
|
||||
|
@ -937,6 +931,68 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResource() throws IOException {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("James");
|
||||
patient.setBirthDate(new DateDt("2011-02-02"));
|
||||
|
||||
Parameters input = new Parameters();
|
||||
input.addParameter().setName("resource").setResource(patient);
|
||||
|
||||
String inputStr = ourFhirCtx.newXmlParser().encodeResourceToString(input);
|
||||
ourLog.info(inputStr);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
|
||||
post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(resp);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void testValidateResourceHuge() throws IOException {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("James" + StringUtils.leftPad("James", 1000000, 'A'));;
|
||||
patient.setBirthDate(new DateDt("2011-02-02"));
|
||||
|
||||
Parameters input = new Parameters();
|
||||
input.addParameter().setName("resource").setResource(patient);
|
||||
|
||||
String inputStr = ourFhirCtx.newXmlParser().encodeResourceToString(input);
|
||||
ourLog.info(inputStr);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
|
||||
post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(resp);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
private List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {
|
||||
List<IdDt> list = new ArrayList<IdDt>();
|
||||
for (BundleEntry next : found.getEntries()) {
|
||||
list.add(next.getResource().getId().toUnqualifiedVersionless());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
|
|
|
@ -135,7 +135,7 @@ public class TestRestfulServer extends RestfulServer {
|
|||
registerInterceptor(new ResponseHighlighterInterceptor());
|
||||
|
||||
/*
|
||||
* Default to XML and pretty printing
|
||||
* Default to JSON with pretty printing
|
||||
*/
|
||||
setDefaultPrettyPrint(true);
|
||||
setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package ca.uhn.fhirtest.rp;
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.JpaResourceProviderDstu2;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
public class FhirtestBaseResourceProviderDstu2<T extends IResource> extends JpaResourceProviderDstu2<T> {
|
||||
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
<bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor">
|
||||
<property name="loggerName" value="fhirtest.access"/>
|
||||
<property name="messageFormat"
|
||||
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]"/>
|
||||
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -36,6 +36,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
|||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.AddressDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.AttachmentDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
|
@ -116,6 +117,30 @@ public class XmlParserTest {
|
|||
assertEquals("OrgName", ((MyOrganization) parse.getSomeOrganization().getResource()).getName().getValue());
|
||||
}
|
||||
|
||||
|
||||
// @Test
|
||||
public void testParseAndEncodeHugeValue() {
|
||||
int len = 1000000;
|
||||
byte[] bytes = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
bytes[i] = (byte) (Math.random() * Byte.MAX_VALUE);
|
||||
}
|
||||
|
||||
AttachmentDt att = new AttachmentDt();
|
||||
att.setData(bytes);
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setValue(att);
|
||||
|
||||
String str = ourCtx.newXmlParser().encodeResourceToString(obs);
|
||||
assertThat(str.length(), Matchers.greaterThan(len));
|
||||
|
||||
obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
|
||||
att = (AttachmentDt) obs.getValue();
|
||||
assertEquals(bytes, att.getData().getValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test for #82 - Not yet enabled because the test won't pass
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
@ -16,7 +17,7 @@ import ca.uhn.fhir.model.dstu.resource.Patient;
|
|||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchParameter;
|
||||
|
||||
|
@ -48,7 +49,7 @@ public class ResourceMethodTest {
|
|||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
|
||||
assertEquals(false, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
|
||||
assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -63,7 +64,7 @@ public class ResourceMethodTest {
|
|||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("mrn");
|
||||
assertEquals(true, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
|
||||
assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -80,7 +81,7 @@ public class ResourceMethodTest {
|
|||
inputParams.add("firstName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
assertEquals(true, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
|
||||
assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,7 +99,7 @@ public class ResourceMethodTest {
|
|||
inputParams.add("lastName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
Request params = Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
|
||||
RequestDetails params = RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
|
||||
boolean actual = rm.incomingServerRequestMatchesMethod(params);
|
||||
assertTrue( actual); // True
|
||||
}
|
||||
|
@ -119,6 +120,6 @@ public class ResourceMethodTest {
|
|||
inputParams.add("mrn");
|
||||
inputParams.add("foo");
|
||||
|
||||
assertEquals(false, rm.incomingServerRequestMatchesMethod(Request.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
|
||||
assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ import ca.uhn.fhir.util.PortUtil;
|
|||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class ValidateTest {
|
||||
public class ValidateDstu1Test {
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static EncodingEnum ourLastEncoding;
|
||||
private static String ourLastResourceBody;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateTest.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu1Test.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
|
|
@ -141,3 +141,4 @@ local.properties
|
|||
/target/
|
||||
/target/
|
||||
/target/
|
||||
/target/
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
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.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.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class ValidateDstu2Test {
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static EncodingEnum ourLastEncoding;
|
||||
private static String ourLastResourceBody;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu2Test.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static BaseOperationOutcome ourOutcomeToReturn;
|
||||
private static ValidationModeEnum ourLastMode;
|
||||
private static String ourLastProfile;
|
||||
|
||||
@Before()
|
||||
public void before() {
|
||||
ourLastResourceBody = null;
|
||||
ourLastEncoding = null;
|
||||
ourOutcomeToReturn = null;
|
||||
ourLastMode = null;
|
||||
ourLastProfile = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateWithOptions() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("001");
|
||||
patient.addIdentifier().setValue("002");
|
||||
|
||||
Parameters params = new Parameters();
|
||||
params.addParameter().setName("resource").setResource(patient);
|
||||
params.addParameter().setName("profile").setValue(new StringDt("http://foo"));
|
||||
params.addParameter().setName("mode").setValue(new StringDt(ValidationModeEnum.CREATE.name()));
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<OperationOutcome"));
|
||||
assertEquals("http://foo", ourLastProfile);
|
||||
assertEquals(ValidationModeEnum.CREATE, ourLastMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidate() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("001");
|
||||
patient.addIdentifier().setValue("002");
|
||||
|
||||
Parameters params = new Parameters();
|
||||
params.addParameter().setName("resource").setResource(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<OperationOutcome"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateWithResults() throws Exception {
|
||||
|
||||
ourOutcomeToReturn = new OperationOutcome();
|
||||
ourOutcomeToReturn.addIssue().setDetails("FOOBAR");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("001");
|
||||
patient.addIdentifier().setValue("002");
|
||||
|
||||
Parameters params = new Parameters();
|
||||
params.addParameter().setName("resource").setResource(patient);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<OperationOutcome", "FOOBAR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateWithNoParsed() throws Exception {
|
||||
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setValue("001");
|
||||
org.addIdentifier().setValue("002");
|
||||
|
||||
Parameters params = new Parameters();
|
||||
params.addParameter().setName("resource").setResource(org);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Organization/$validate");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newJsonParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(ourLastResourceBody, stringContainsInOrder("\"resourceType\":\"Organization\"", "\"identifier\"", "\"value\":\"001"));
|
||||
assertEquals(EncodingEnum.JSON, ourLastEncoding);
|
||||
|
||||
}
|
||||
|
||||
@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();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider, new OrganizationProvider());
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
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 {
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile) {
|
||||
IdDt id = new IdDt(thePatient.getIdentifier().get(0).getValue());
|
||||
if (thePatient.getId().isEmpty() == false) {
|
||||
id = thePatient.getId();
|
||||
}
|
||||
|
||||
ourLastMode = theMode;
|
||||
ourLastProfile = theProfile;
|
||||
|
||||
MethodOutcome outcome = new MethodOutcome(id.withVersion("002"));
|
||||
outcome.setOperationOutcome(ourOutcomeToReturn);
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class OrganizationProvider implements IResourceProvider {
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validate(@ResourceParam String theResourceBody, @ResourceParam EncodingEnum theEncoding) {
|
||||
ourLastResourceBody = theResourceBody;
|
||||
ourLastEncoding = theEncoding;
|
||||
|
||||
return new MethodOutcome(new IdDt("001"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Organization.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -26,13 +28,18 @@ import org.junit.Test;
|
|||
import org.mockito.ArgumentCaptor;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
|
@ -51,17 +58,15 @@ public class LoggingInterceptorTest {
|
|||
private static RestfulServer servlet;
|
||||
private IServerInterceptor myInterceptor;
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
|
||||
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
@ -73,14 +78,14 @@ public class LoggingInterceptorTest {
|
|||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
interceptor.setMessageFormat( "${operationType} - ${idOrResourceName} - ${requestParameters}");
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
|
||||
|
||||
interceptor.setMessageFormat("${operationType} - ${idOrResourceName} - ${requestParameters}");
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_id=1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
@ -89,16 +94,16 @@ public class LoggingInterceptorTest {
|
|||
verify(logger, times(1)).info(captor.capture());
|
||||
assertThat(captor.getValue(), StringContains.containsString("search-type - Patient - ?_id=1"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMetadata() throws Exception {
|
||||
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
|
||||
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
@ -108,8 +113,63 @@ public class LoggingInterceptorTest {
|
|||
assertThat(captor.getValue(), StringContains.containsString("metadata - "));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testOperationOnInstance() throws Exception {
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$everything");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(logger, times(1)).info(captor.capture());
|
||||
assertEquals("extended-operation-instance - $everything - Patient/123", captor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationOnServer() throws Exception {
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$everything");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(logger, times(1)).info(captor.capture());
|
||||
assertEquals("extended-operation-server - $everything - ", captor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationOnType() throws Exception {
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
interceptor.setMessageFormat("${operationType} - ${operationName} - ${idOrResourceName}");
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||
|
||||
Logger logger = mock(Logger.class);
|
||||
interceptor.setLogger(logger);
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$everything");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(logger, times(1)).info(captor.capture());
|
||||
assertEquals("extended-operation-type - $everything - Patient", captor.getValue());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
|
@ -121,17 +181,17 @@ public class LoggingInterceptorTest {
|
|||
servlet.setInterceptors(Collections.singletonList(myInterceptor));
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
|
||||
servlet.setResourceProviders(new DummyPatientResourceProvider());
|
||||
servlet.setPlainProviders(new PlainProvider());
|
||||
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
|
@ -164,7 +224,7 @@ public class LoggingInterceptorTest {
|
|||
patient.getName().add(new HumanNameDt());
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientTwo");
|
||||
patient.getGender().setText("F");
|
||||
patient.setGender(AdministrativeGenderEnum.FEMALE);
|
||||
patient.getId().setValue("2");
|
||||
idToPatient.put("2", patient);
|
||||
}
|
||||
|
@ -185,7 +245,6 @@ public class LoggingInterceptorTest {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the resource by its identifier
|
||||
*
|
||||
|
@ -203,12 +262,27 @@ public class LoggingInterceptorTest {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Operation(name = "$everything", idempotent = true)
|
||||
public Bundle patientTypeOperation(@IdParam IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||
|
||||
Bundle retVal = new Bundle();
|
||||
// Populate bundle with matching resources
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Operation(name = "$everything", idempotent = true)
|
||||
public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||
|
||||
Bundle retVal = new Bundle();
|
||||
// Populate bundle with matching resources
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private Patient createPatient1() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier();
|
||||
|
@ -218,11 +292,23 @@ public class LoggingInterceptorTest {
|
|||
patient.addName();
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
patient.setGender(AdministrativeGenderEnum.MALE);
|
||||
patient.getId().setValue("1");
|
||||
return patient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PlainProvider {
|
||||
|
||||
@Operation(name = "$everything", idempotent = true)
|
||||
public Bundle patientTypeOperation(@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||
|
||||
Bundle retVal = new Bundle();
|
||||
// Populate bundle with matching resources
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -191,17 +191,36 @@
|
|||
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<show>public</show>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>${maven_license_plugin_version}</version>
|
||||
<configuration>
|
||||
<!-- Don't add UHN licenses to RI structures -->
|
||||
<skipUpdateLicense>true</skipUpdateLicense>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<verbose>true</verbose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
4
pom.xml
4
pom.xml
|
@ -230,8 +230,8 @@
|
|||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<compilerId>javac-with-errorprone</compilerId>
|
||||
<forceJavacCompilerUse>true</forceJavacCompilerUse>
|
||||
<!-- <compilerId>javac-with-errorprone</compilerId>
|
||||
<forceJavacCompilerUse>true</forceJavacCompilerUse> -->
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
|
@ -55,6 +55,9 @@
|
|||
<action type="add">
|
||||
Web tester UI now supports _revinclude
|
||||
</action>
|
||||
<action type="add">
|
||||
LoggingInterceptor for server now supports logging DSTU2 extended operations by name
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.0" date="2015-May-8">
|
||||
<action type="add">
|
||||
|
|
|
@ -1059,6 +1059,17 @@
|
|||
operation tests whether a resource passes business validation, and would be
|
||||
acceptable for saving to a server (e.g. by a create or update method).
|
||||
</p>
|
||||
<p class="doc_info_bubble">
|
||||
<b>Note on FHIR versions:</b>
|
||||
In FHIR DSTU1 the validate operation used a URL resembling <code>http://example.com/Patient/_validate</code>
|
||||
with a resource in the HTTP POST body. In FHIR DSTU2, validate has been changed to use the
|
||||
<a href="#extended_operations">extended operation</a> mechanism. It now uses a URL
|
||||
resembling <code>http://example.com/Patient/$validate</code> and takes a
|
||||
Parameters resource as input in the method body.<br/><br/>
|
||||
The mechanism described below may be used for both DSTU1 and DSTU2+ servers, and HAPI
|
||||
will automatically use the correct form depending on what FHIR version the
|
||||
server is configured to use.
|
||||
</p>
|
||||
<p>
|
||||
Validate methods must be annotated with the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Validate.html">@Validate</a>
|
||||
|
@ -1107,11 +1118,20 @@
|
|||
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
In the example above, only the <code>@ResourceParam</code> parameter is technically required, but
|
||||
in DSTU2 you are encouraged to also add the following parameters:
|
||||
</p>
|
||||
<ul>
|
||||
<li><b>@Validate.Mode ValidationModeEnum mode</b> - This is the validation mode (see the FHIR specification for information on this)</li>
|
||||
<li><b>@Validate.Profile String profile</b> - This is the profile to validate against (see the FHIR specification for more information on this)</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method (this would be invoked using an HTTP POST,
|
||||
with the resource in the POST body):
|
||||
with a Parameters resource in the POST body):
|
||||
<br />
|
||||
<code>http://fhir.example.com/Patient/_validate</code>
|
||||
<code>http://fhir.example.com/Patient/$validate</code>
|
||||
</p>
|
||||
|
||||
<a name="system_conformance" />
|
||||
|
@ -1508,6 +1528,7 @@
|
|||
<code>http://fhir.example.com/Patient/123/Condition</code>
|
||||
</p>
|
||||
|
||||
<a name="extended_operations"/>
|
||||
</section>
|
||||
|
||||
<section name="Extended Operations">
|
||||
|
|
Loading…
Reference in New Issue