More work on removing legacy code

This commit is contained in:
James Agnew 2017-07-30 06:43:25 -04:00
parent 92224c2532
commit ebd3eeb5ee
19 changed files with 214 additions and 822 deletions

View File

@ -1,85 +0,0 @@
package ca.uhn.fhir.rest.annotation;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
/**
* RESTful method annotation to be used for the FHIR <a
* href="http://hl7.org/implement/standards/fhir/http.html#tags">Tag
* Operations</a> which have to do with getting tags.
* <ul>
* <li>
* To return a global list of all tags on the server, this annotation should not
* contain a {@link #type()} attribute, and the method should not have an ID or
* Version ID parameter. On server implementations, the method must be defined
* in a <a href=
* "http://jamesagnew.github.io/hapi-fhir/doc_rest_server.html#plain_providers"
* >plain provider</a>.</li>
* <li>
* To return a list of all tags on the server <b>for the given resource
* type</b>, this annotation should contain a {@link #type()} attribute
* specifying the resource type, and the method should not have an ID or Version
* ID parameter. Note that for a server implementation, the {@link #type()}
* annotation is optional if the method is defined in a <a href=
* "http://jamesagnew.github.io/hapi-fhir/doc_rest_server.html#resource_providers"
* >resource provider</a>, since the type is implied.</li>
* <li>
* To return a list of all tags on the server <b>for the given resource
* instance</b>, this annotation should contain a {@link #type()} attribute
* specifying the resource type, and the method should have a parameter of type
* {@link IdDt} annotated with the {@link IdParam} annotation. Note that for a
* server implementation, the {@link #type()} annotation is optional if the
* method is defined in a <a href=
* "http://jamesagnew.github.io/hapi-fhir/doc_rest_server.html#resource_providers"
* >resource provider</a>, since the type is implied.</li>
* <li>
* To return a list of all tags on the server <b>for the given version of the
* resource instance</b>, this annotation should contain a {@link #type()}
* attribute specifying the resource type, and the method should have a
* parameter of type {@link IdDt} annotated with the {@link VersionIdParam}
* annotation, <b>and</b> a parameter of type {@link IdDt} annotated with the
* {@link IdParam} annotation. Note that for a server implementation, the
* {@link #type()} annotation is optional if the method is defined in a <a href=
* "http://jamesagnew.github.io/hapi-fhir/doc_rest_server.html#resource_providers"
* >resource provider</a>, since the type is implied.</li>
* </ul>
*/
@Target(value= ElementType.METHOD)
@Retention(value=RetentionPolicy.RUNTIME)
public @interface GetTags {
/**
* If set to a type other than the default (which is {@link IResource}
* , this method is expected to return a TagList containing only tags which
* are specific to the given resource type.
*/
Class<? extends IBaseResource> type() default IBaseResource.class;
}

View File

@ -22,7 +22,6 @@ package ca.uhn.fhir.rest.client.api;
import java.util.List; import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
@ -35,61 +34,21 @@ import ca.uhn.fhir.rest.gclient.*;
public interface IGenericClient extends IRestfulClient { public interface IGenericClient extends IRestfulClient {
/**
* Retrieves and returns the server conformance statement
*
* @deprecated Use {@link #fetchConformance()} instead
*/
@Deprecated
IBaseConformance conformance();
/** /**
* Fluent method for the "create" operation, which creates a new resource instance on the server * Fluent method for the "create" operation, which creates a new resource instance on the server
*/ */
ICreate create(); ICreate create();
/**
* Implementation of the "type create" method.
*
* @param theResource
* The resource to create
* @return An outcome
* @deprecated Use {@link #create() fluent method instead}. This method will be removed.
*
*/
@Deprecated
MethodOutcome create(IBaseResource theResource);
/** /**
* Fluent method for the "delete" operation, which performs a logical delete on a server resource * Fluent method for the "delete" operation, which performs a logical delete on a server resource
*/ */
IDelete delete(); IDelete delete();
/**
* Implementation of the "delete instance" method.
*
* @param theType
* The type of resource to delete
* @param theId
* the ID of the resource to delete
* @return An outcome
* @deprecated Use {@link #delete()} instead
*/
@Deprecated
MethodOutcome delete(Class<? extends IBaseResource> theType, IdDt theId);
/**
* Implementation of the "delete instance" method.
*
* @param theType
* The type of resource to delete
* @param theId
* the ID of the resource to delete
* @return An outcome
* @deprecated Use {@link #delete()} instead
*/
@Deprecated
MethodOutcome delete(Class<? extends IBaseResource> theType, String theId);
/** /**
* Retrieves the server's conformance statement * Retrieves the server's conformance statement
@ -106,11 +65,6 @@ public interface IGenericClient extends IRestfulClient {
*/ */
void forceConformanceCheck() throws FhirClientConnectionException; void forceConformanceCheck() throws FhirClientConnectionException;
/**
* Fluent method for the "get tags" operation
*/
IGetTags getTags();
/** /**
* Implementation of the "history" method * Implementation of the "history" method
*/ */
@ -118,8 +72,6 @@ public interface IGenericClient extends IRestfulClient {
/** /**
* Loads the previous/next bundle of resources from a paged set, using the link specified in the "link type=next" tag within the atom bundle. * Loads the previous/next bundle of resources from a paged set, using the link specified in the "link type=next" tag within the atom bundle.
*
* @see Bundle#getLinkNext()
*/ */
IGetPage loadPage(); IGetPage loadPage();

View File

@ -1,35 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 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 org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.TagList;
public interface IGetTags extends IClientExecutable<IGetTags, TagList> {
IGetTags forResource(Class<? extends IBaseResource> theClass);
IGetTags forResource(Class<? extends IBaseResource> theClass, String theId);
IGetTags forResource(Class<? extends IBaseResource> theClass, String theId, String theVersionId);
}

View File

@ -138,4 +138,6 @@ public interface IQuery extends IBaseQuery<IQuery> {
@Override @Override
IQuery and(ICriterion<?> theCriterion); IQuery and(ICriterion<?> theCriterion);
// <T extends IBaseBundle> T execute();
} }

View File

@ -1,11 +1,7 @@
package ca.uhn.fhir.rest.gclient; package ca.uhn.fhir.rest.gclient;
public interface IQueryTyped<T> extends IQuery, IClientExecutable<IClientExecutable<?,?>, T> { import org.hl7.fhir.instance.model.api.IBaseBundle;
/** public interface IQueryTyped<T extends IBaseBundle> extends IQuery, IClientExecutable<IClientExecutable<?,?>, T> {
* Actually execute the client operation
*/
@Override
T execute();
} }

View File

@ -26,15 +26,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.api.RequestTypeEnum;
/** /**
@ -143,6 +137,13 @@ public class BundleUtil {
* Extract all of the resources from a given bundle * Extract all of the resources from a given bundle
*/ */
public static List<IBaseResource> toListOfResources(FhirContext theContext, IBaseBundle theBundle) { public static List<IBaseResource> toListOfResources(FhirContext theContext, IBaseBundle theBundle) {
return toListOfResourcesOfType(theContext, theBundle, null);
}
/**
* Extract all of the resources of a given type from a given bundle
*/
public static List<IBaseResource> toListOfResourcesOfType(FhirContext theContext, IBaseBundle theBundle, Class<? extends IBaseResource> theTypeToInclude) {
List<IBaseResource> retVal = new ArrayList<IBaseResource>(); List<IBaseResource> retVal = new ArrayList<IBaseResource>();
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
@ -153,6 +154,9 @@ public class BundleUtil {
BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource");
for (IBase nextEntry : entries) { for (IBase nextEntry : entries) {
for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) { for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) {
if (theTypeToInclude != null && !theTypeToInclude.isAssignableFrom(next.getClass())) {
continue;
}
retVal.add((IBaseResource) next); retVal.add((IBaseResource) next);
} }
} }

View File

@ -25,7 +25,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -33,7 +32,8 @@ import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*; import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.base.resource.BaseConformance; import ca.uhn.fhir.model.base.resource.BaseConformance;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.primitive.*; import ca.uhn.fhir.model.primitive.*;
@ -217,10 +217,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return theResource.getIdElement().getIdPart(); return theResource.getIdElement().getIdPart();
} }
@Override
public IGetTags getTags() {
return new GetTagsInternal();
}
@Override @Override
public IHistory history() { public IHistory history() {
@ -228,36 +224,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
} }
private Class<? extends IBaseResource> inferResourceClass(UriDt theUrl) {
String urlString = theUrl.getValueAsString();
int i = urlString.indexOf('?');
if (i >= 0) {
urlString = urlString.substring(0, i);
}
i = urlString.indexOf("://");
if (i >= 0) {
urlString = urlString.substring(i + 3);
}
String[] pcs = urlString.split("\\/");
for (i = pcs.length - 1; i >= 0; i--) {
String s = pcs[i].trim();
if (!s.isEmpty()) {
RuntimeResourceDefinition def = myContext.getResourceDefinition(s);
if (def != null) {
return def.getImplementingClass();
}
}
}
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
}
// @Override // @Override
// public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) { // public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) {
@ -324,40 +291,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new SearchInternal(); return new SearchInternal();
} }
@Override
public <T extends IBaseResource> Bundle search(final Class<T> theType, Map<String, List<IQueryParameterType>> theParams) {
LinkedHashMap<String, List<String>> params = new LinkedHashMap<String, List<String>>();
for (Entry<String, List<IQueryParameterType>> nextEntry : theParams.entrySet()) {
ArrayList<String> valueList = new ArrayList<String>();
String qualifier = null;
for (IQueryParameterType nextValue : nextEntry.getValue()) {
valueList.add(nextValue.getValueAsQueryToken(myContext));
qualifier = nextValue.getQueryParameterQualifier();
}
qualifier = StringUtils.defaultString(qualifier);
params.put(nextEntry.getKey() + qualifier, valueList);
}
BaseHttpClientInvocation invocation = SearchMethodBinding.createSearchInvocation(myContext, toResourceName(theType), params, null, null, null);
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
}
BundleResponseHandler binding = new BundleResponseHandler(theType);
Bundle resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
return resp;
}
@Override
public <T extends IBaseResource> Bundle search(final Class<T> theType, UriDt theUrl) {
BaseHttpClientInvocation invocation = new HttpGetClientInvocation(getFhirContext(), theUrl.getValueAsString());
return invokeClient(myContext, new BundleResponseHandler(theType), invocation);
}
@Override
public Bundle search(UriDt theUrl) {
return search(inferResourceClass(theUrl), theUrl);
}
/** /**
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change! * For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
@ -381,18 +314,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new TransactionInternal(); return new TransactionInternal();
} }
@Deprecated // override deprecated method
@Override
public List<IBaseResource> transaction(List<IBaseResource> theResources) {
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(theResources, myContext);
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
}
Bundle resp = invokeClient(myContext, new BundleResponseHandler(null), invocation, myLogRequestAndResponse);
return new ArrayList<IBaseResource>(resp.toListOfResources());
}
@Override @Override
public IPatch patch() { public IPatch patch() {
@ -680,7 +601,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
addPreferHeader(myPrefer, invocation); addPreferHeader(myPrefer, invocation);
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
OutcomeResponseHandler binding = new OutcomeResponseHandler(myPrefer); OutcomeResponseHandler binding = new OutcomeResponseHandler(myPrefer);
Map<String, List<String>> params = new HashMap<String, List<String>>(); Map<String, List<String>> params = new HashMap<String, List<String>>();
@ -877,10 +797,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
private Class<? extends IBaseBundle> myBundleType; private Class<? extends IBaseBundle> myBundleType;
private String myUrl; private String myUrl;
public GetPageInternal(String theUrl) {
myUrl = theUrl;
}
public GetPageInternal(String theUrl, Class<? extends IBaseBundle> theBundleType) { public GetPageInternal(String theUrl, Class<? extends IBaseBundle> theBundleType) {
myUrl = theUrl; myUrl = theUrl;
myBundleType = theBundleType; myBundleType = theBundleType;
@ -889,11 +805,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override @Override
public Object execute() { public Object execute() {
IClientResponseHandler binding; IClientResponseHandler binding;
if (myBundleType == null) { binding = new ResourceResponseHandler(myBundleType, getPreferResponseTypes());
binding = new BundleResponseHandler(null);
} else {
binding = new ResourceResponseHandler(myBundleType, getPreferResponseTypes());
}
HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myContext, myUrl); HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myContext, myUrl);
Map<String, List<String>> params = null; Map<String, List<String>> params = null;
@ -902,71 +814,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
} }
private class GetTagsInternal extends BaseClientExecutable<IGetTags, TagList> implements IGetTags {
private String myId;
private String myResourceName;
private String myVersionId;
@Override
public TagList execute() {
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
Map<String, List<String>> initial = createExtraParams();
if (initial != null) {
params.putAll(initial);
}
TagListResponseHandler binding = new TagListResponseHandler();
List<String> urlFragments = new ArrayList<String>();
if (isNotBlank(myResourceName)) {
urlFragments.add(myResourceName);
if (isNotBlank(myId)) {
urlFragments.add(myId);
if (isNotBlank(myVersionId)) {
urlFragments.add(Constants.PARAM_HISTORY);
urlFragments.add(myVersionId);
}
}
}
urlFragments.add(Constants.PARAM_TAGS);
HttpGetClientInvocation invocation = new HttpGetClientInvocation(myContext, params, urlFragments);
return invoke(params, binding, invocation);
}
@Override
public IGetTags forResource(Class<? extends IBaseResource> theClass) {
setResourceClass(theClass);
return this;
}
@Override
public IGetTags forResource(Class<? extends IBaseResource> theClass, String theId) {
setResourceClass(theClass);
myId = theId;
return this;
}
@Override
public IGetTags forResource(Class<? extends IBaseResource> theClass, String theId, String theVersionId) {
setResourceClass(theClass);
myId = theId;
myVersionId = theVersionId;
return this;
}
private void setResourceClass(Class<? extends IBaseResource> theClass) {
if (theClass != null) {
myResourceName = myContext.getResourceDefinition(theClass).getName();
} else {
myResourceName = null;
}
}
}
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped { private class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped {
@ -980,16 +827,11 @@ public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public IHistoryTyped andReturnBundle(Class theType) { public IHistoryTyped andReturnBundle(Class theType) {
Validate.notNull(theType, "theType must not be null on method andReturnBundle(Class)");
myReturnType = theType; myReturnType = theType;
return this; return this;
} }
@SuppressWarnings("unchecked")
@Override
public IHistoryTyped andReturnDstu1Bundle() {
return this;
}
@Override @Override
public IHistoryTyped count(Integer theCount) { public IHistoryTyped count(Integer theCount) {
myCount = theCount; myCount = theCount;
@ -1015,11 +857,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(myContext, resourceName, id, mySince, myCount); HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(myContext, resourceName, id, mySince, myCount);
IClientResponseHandler handler; IClientResponseHandler handler;
if (myReturnType != null) { handler = new ResourceResponseHandler(myReturnType, getPreferResponseTypes(myType));
handler = new ResourceResponseHandler(myReturnType, getPreferResponseTypes(myType));
} else {
handler = new BundleResponseHandler(null);
}
return invoke(null, handler, invocation); return invoke(null, handler, invocation);
} }
@ -1075,10 +913,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new GetPageInternal(myPageUrl, theBundleType); return new GetPageInternal(myPageUrl, theBundleType);
} }
@Override
public IGetPageTyped andReturnDstu1Bundle() {
return new GetPageInternal(myPageUrl);
}
@Override @Override
public IGetPageUntyped byUrl(String thePageUrl) { public IGetPageUntyped byUrl(String thePageUrl) {
@ -1089,10 +923,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this; return this;
} }
@Override
public IGetPageTyped next(Bundle theBundle) {
return new GetPageInternal(theBundle.getLinkNext().getValue());
}
@Override @Override
public <T extends IBaseBundle> IGetPageTyped<T> next(T theBundle) { public <T extends IBaseBundle> IGetPageTyped<T> next(T theBundle) {
@ -1127,21 +957,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "noPagingLinkFoundInBundle", theWantRel)); throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "noPagingLinkFoundInBundle", theWantRel));
} }
@Override
public IGetPageTyped previous(Bundle theBundle) {
return new GetPageInternal(theBundle.getLinkPrevious().getValue());
}
@Override @Override
public <T extends IBaseBundle> IGetPageTyped<T> previous(T theBundle) { public <T extends IBaseBundle> IGetPageTyped<T> previous(T theBundle) {
return nextOrPrevious(PREVIOUS, theBundle); return nextOrPrevious(PREVIOUS, theBundle);
} }
@Deprecated // override deprecated method
@Override
public IGetPageTyped url(String thePageUrl) {
return new GetPageInternal(thePageUrl);
}
} }
@ -1757,12 +1578,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
private final class ResourceListResponseHandler implements IClientResponseHandler<List<IBaseResource>> { private final class ResourceListResponseHandler implements IClientResponseHandler<List<IBaseResource>> {
private Class<? extends IBaseResource> myType;
public ResourceListResponseHandler(Class<? extends IBaseResource> theType) {
myType = theType;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public List<IBaseResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) public List<IBaseResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders)
@ -2141,18 +1956,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
} }
} }
private final class TagListResponseHandler implements IClientResponseHandler<TagList> {
@Override
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
if (respType == null) {
throw NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
}
IParser parser = respType.newParser(myContext);
return parser.parseTagList(theResponseReader);
}
}
private final class TransactionExecutable<T> extends BaseClientExecutable<ITransactionTyped<T>, T> implements ITransactionTyped<T> { private final class TransactionExecutable<T> extends BaseClientExecutable<ITransactionTyped<T>, T> implements ITransactionTyped<T> {
@ -2182,14 +1985,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
public T execute() { public T execute() {
Map<String, List<String>> params = new HashMap<String, List<String>>(); Map<String, List<String>> params = new HashMap<String, List<String>>();
if (myResources != null) { if (myResources != null) {
ResourceListResponseHandler binding = new ResourceListResponseHandler(null); ResourceListResponseHandler binding = new ResourceListResponseHandler();
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myResources, myContext); BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myResources, myContext);
return (T) invoke(params, binding, invocation); return (T) invoke(params, binding, invocation);
} else if (myBaseBundle != null) { } else if (myBaseBundle != null) {
ResourceResponseHandler binding = new ResourceResponseHandler(myBaseBundle.getClass(), getPreferResponseTypes()); ResourceResponseHandler binding = new ResourceResponseHandler(myBaseBundle.getClass(), getPreferResponseTypes());
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBaseBundle, myContext); BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBaseBundle, myContext);
return (T) invoke(params, binding, invocation); return (T) invoke(params, binding, invocation);
} else if (myRawBundle != null) { // } else if (myRawBundle != null) {
} else {
StringResponseHandler binding = new StringResponseHandler(); StringResponseHandler binding = new StringResponseHandler();
/* /*
* If the user has explicitly requested a given encoding, we may need to re-encode the raw string * If the user has explicitly requested a given encoding, we may need to re-encode the raw string
@ -2202,10 +2006,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
} }
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myRawBundle, myContext); BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myRawBundle, myContext);
return (T) invoke(params, binding, invocation); return (T) invoke(params, binding, invocation);
} else {
BundleResponseHandler binding = new BundleResponseHandler(null);
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBundle, myContext);
return (T) invoke(params, binding, invocation);
} }
} }
@ -2213,11 +2013,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
private final class TransactionInternal implements ITransaction { private final class TransactionInternal implements ITransaction {
@Override
public ITransactionTyped<Bundle> withBundle(Bundle theBundle) {
Validate.notNull(theBundle, "theBundle must not be null");
return new TransactionExecutable<Bundle>(theBundle);
}
@Override @Override
public ITransactionTyped<String> withBundle(String theBundle) { public ITransactionTyped<String> withBundle(String theBundle) {
@ -2420,7 +2215,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
addPreferHeader(myPrefer, invocation); addPreferHeader(myPrefer, invocation);
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
OutcomeResponseHandler binding = new OutcomeResponseHandler(myPrefer); OutcomeResponseHandler binding = new OutcomeResponseHandler(myPrefer);
Map<String, List<String>> params = new HashMap<String, List<String>>(); Map<String, List<String>> params = new HashMap<String, List<String>>();

View File

@ -25,8 +25,8 @@ import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu2Interceptor; import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu2Interceptor;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider; import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
@ -131,7 +131,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
protected List<IdDt> toIdListUnqualifiedVersionless(Bundle found) { protected List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {
List<IdDt> list = new ArrayList<IdDt>(); List<IdDt> list = new ArrayList<IdDt>();
for (BundleEntry next : found.getEntries()) { for (Entry next : found.getEntry()) {
list.add(next.getResource().getId().toUnqualifiedVersionless()); list.add(next.getResource().getId().toUnqualifiedVersionless());
} }
return list; return list;
@ -139,7 +139,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
protected List<String> toNameList(Bundle resp) { protected List<String> toNameList(Bundle resp) {
List<String> names = new ArrayList<String>(); List<String> names = new ArrayList<String>();
for (BundleEntry next : resp.getEntries()) { for (Entry next : resp.getEntry()) {
Patient nextPt = (Patient) next.getResource(); Patient nextPt = (Patient) next.getResource();
String nextStr = nextPt.getNameFirstRep().getGivenAsSingleString() + " " + nextPt.getNameFirstRep().getFamilyAsSingleString(); String nextStr = nextPt.getNameFirstRep().getGivenAsSingleString() + " " + nextPt.getNameFirstRep().getFamilyAsSingleString();
if (isNotBlank(nextStr)) { if (isNotBlank(nextStr)) {

View File

@ -19,10 +19,11 @@ import org.junit.*;
import org.junit.Test; import org.junit.Test;
import org.springframework.test.util.AopTestUtils; import org.springframework.test.util.AopTestUtils;
import com.google.common.base.Charsets;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu2.composite.*; import ca.uhn.fhir.model.dstu2.composite.*;
import ca.uhn.fhir.model.dstu2.resource.*; import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
@ -33,10 +34,10 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*; import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.gclient.*;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.*; import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.*;
import ca.uhn.fhir.util.UrlUtil;
public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
@ -451,13 +452,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
} }
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute(); ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(10).execute(); Bundle found = ourClient
assertEquals(100, found.getTotalResults().getValue().intValue()); .search()
assertEquals(10, found.getEntries().size()); .forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(10)
.execute();
assertEquals(100, found.getTotalElement().getValue().intValue());
assertEquals(10, found.getEntry().size());
found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(999).execute(); found = ourClient
assertEquals(100, found.getTotalResults().getValue().intValue()); .search()
assertEquals(50, found.getEntries().size()); .forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(999)
.execute();
assertEquals(100, found.getTotalElement().getValue().intValue());
assertEquals(50, found.getEntry().size());
} }
@ -688,18 +699,16 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date())); location.setPeriod(new PeriodDt().setStartWithSecondsPrecision(new Date()).setEndWithSecondsPrecision(new Date()));
IIdType e1id = ourClient.create().resource(e1).execute().getId(); IIdType e1id = ourClient.create().resource(e1).execute().getId();
//@formatter:off
Bundle res = ourClient.search() Bundle res = ourClient.search()
.forResource(Encounter.class) .forResource(Encounter.class)
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1")) .where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
.include(Encounter.INCLUDE_LOCATION.asRecursive()) .include(Encounter.INCLUDE_LOCATION.asRecursive())
.include(Location.INCLUDE_PARTOF.asRecursive()) .include(Location.INCLUDE_PARTOF.asRecursive())
.execute(); .execute();
//@formatter:on
assertEquals(3, res.size()); assertEquals(3, res.getEntry().size());
assertEquals(1, res.getResources(Encounter.class).size()); assertEquals(1, BundleUtil.toListOfResourcesOfType(myFhirCtx, res, Encounter.class).size());
assertEquals(e1id.toUnqualifiedVersionless(), res.getResources(Encounter.class).get(0).getId().toUnqualifiedVersionless()); assertEquals(e1id.toUnqualifiedVersionless(), BundleUtil.toListOfResourcesOfType(myFhirCtx, res, Encounter.class).get(0).getIdElement().toUnqualifiedVersionless());
} }
@ -889,14 +898,26 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
public void testDiagnosticOrderResources() throws Exception { public void testDiagnosticOrderResources() throws Exception {
IGenericClient client = ourClient; IGenericClient client = ourClient;
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size(); int initialSize = client
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
DiagnosticOrder res = new DiagnosticOrder(); DiagnosticOrder res = new DiagnosticOrder();
res.addIdentifier().setSystem("urn:foo").setValue("123"); res.addIdentifier().setSystem("urn:foo").setValue("123");
client.create().resource(res).execute(); client.create().resource(res).execute();
int newSize = client.search().forResource(DiagnosticOrder.class).execute().size(); int newSize = client
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize); assertEquals(1, newSize - initialSize);
@ -912,12 +933,24 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IGenericClient client = ourClient; IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentManifest.class).execute().size(); int initialSize = client
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"), StandardCharsets.UTF_8); String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"), StandardCharsets.UTF_8);
client.create().resource(resBody).execute(); client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentManifest.class).execute().size(); int newSize = client
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize); assertEquals(1, newSize - initialSize);
@ -930,12 +963,24 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
public void testDocumentReferenceResources() throws Exception { public void testDocumentReferenceResources() throws Exception {
IGenericClient client = ourClient; IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentReference.class).execute().size(); int initialSize = client
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json")); String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"), Charsets.UTF_8);
client.create().resource(resBody).execute(); client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentReference.class).execute().size(); int newSize = client
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize); assertEquals(1, newSize - initialSize);
@ -1307,7 +1352,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent()); IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output); ourLog.info(output);
List<IdDt> ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseBundle(output)); List<IdDt> ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString()); ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pId, cId)); assertThat(ids, containsInAnyOrder(pId, cId));
} finally { } finally {
@ -1322,7 +1367,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent()); IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output); ourLog.info(output);
List<IdDt> ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseBundle(output)); List<IdDt> ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString()); ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pId, cId)); assertThat(ids, containsInAnyOrder(pId, cId));
} finally { } finally {
@ -1417,12 +1462,24 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
public void testImagingStudyResources() throws Exception { public void testImagingStudyResources() throws Exception {
IGenericClient client = ourClient; IGenericClient client = ourClient;
int initialSize = client.search().forResource(ImagingStudy.class).execute().size(); int initialSize = client
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/imagingstudy.json"), StandardCharsets.UTF_8); String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/imagingstudy.json"), StandardCharsets.UTF_8);
client.create().resource(resBody).execute(); client.create().resource(resBody).execute();
int newSize = client.search().forResource(ImagingStudy.class).execute().size(); int newSize = client
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize); assertEquals(1, newSize - initialSize);
@ -1524,15 +1581,28 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
pat = new Patient(); pat = new Patient();
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02"); pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_02");
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId(); ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
{ {
Bundle returned = ourClient.search().forResource(Patient.class).encodedXml().execute(); IQuery a = ourClient
assertThat(returned.size(), greaterThan(1)); .search()
.forResource(Patient.class);
IQueryTyped<Bundle> b = a.returnBundle(Bundle.class);
IClientExecutable<?, ?> x = b.encodedXml();
x.execute();
}
{
Bundle returned = ourClient
.search()
.forResource(Patient.class)
.returnBundle(Bundle.class)
.encodedXml()
.execute();
assertThat(returned.getEntry().size(), greaterThan(1));
assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum()); assertEquals(BundleTypeEnum.SEARCHSET, returned.getType().getValueAsEnum());
} }
{ {
Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute(); Bundle returned = ourClient.search().forResource(Patient.class).encodedJson().execute();
assertThat(returned.size(), greaterThan(1)); assertThat(returned.getEntry().size(), greaterThan(1));
} }
} }
@ -1579,7 +1649,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSaveAndRetrieveWithContained01</td>")); assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSaveAndRetrieveWithContained01</td>"));
Bundle b = ourClient.search().forResource("Patient").where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system:rpdstu2", "testSaveAndRetrieveWithContained01")).prettyPrint().execute(); Bundle b = ourClient.search().forResource("Patient").where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system:rpdstu2", "testSaveAndRetrieveWithContained01")).prettyPrint().execute();
assertEquals(1, b.size()); assertEquals(1, b.getEntry().size());
} }
@ -1646,8 +1716,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint() Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint()
.execute(); .execute();
assertEquals(1, actual.size()); assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
} }
@ -1697,8 +1767,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.where(Patient.ORGANIZATION.hasId(o1id.getIdPart())) .where(Patient.ORGANIZATION.hasId(o1id.getIdPart()))
.encodedJson().prettyPrint().execute(); .encodedJson().prettyPrint().execute();
//@formatter:on //@formatter:on
assertEquals(1, actual.size()); assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
//@formatter:off //@formatter:off
actual = ourClient.search() actual = ourClient.search()
@ -1706,8 +1776,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.where(Patient.ORGANIZATION.hasId(o1id.getValue())) .where(Patient.ORGANIZATION.hasId(o1id.getValue()))
.encodedJson().prettyPrint().execute(); .encodedJson().prettyPrint().execute();
//@formatter:on //@formatter:on
assertEquals(1, actual.size()); assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
} }
@ -1742,7 +1812,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
expectedIds.add(p1Id.getIdPart()); expectedIds.add(p1Id.getIdPart());
expectedIds.add(p2Id.getIdPart()); expectedIds.add(p2Id.getIdPart());
Set<String> actualIds = new HashSet<String>(); Set<String> actualIds = new HashSet<String>();
for (BundleEntry ele : actual.getEntries()) { for (BundleEntry ele : actual.getEntry()) {
actualIds.add(ele.getResource().getId().getIdPart()); actualIds.add(ele.getResource().getId().getIdPart());
} }
assertEquals("Expects to retrieve the 2 patients which reference the two different organizations", expectedIds, actualIds); assertEquals("Expects to retrieve the 2 patients which reference the two different organizations", expectedIds, actualIds);
@ -1765,7 +1835,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.withProfile("http://profileX") .withProfile("http://profileX")
.encodedJson().prettyPrint().execute(); .encodedJson().prettyPrint().execute();
//@formatter:on //@formatter:on
assertEquals("nothing matches profile x", Collections.emptyList(), actual.getEntries()); assertEquals("nothing matches profile x", Collections.emptyList(), actual.getEntry());
//@formatter:off //@formatter:off
actual = ourClient.search() actual = ourClient.search()
.forResource(Organization.class) .forResource(Organization.class)
@ -1776,7 +1846,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
Set<String> expectedIds = new HashSet<String>(); Set<String> expectedIds = new HashSet<String>();
expectedIds.add(o1id.getIdPart()); expectedIds.add(o1id.getIdPart());
Set<String> actualIds = new HashSet<String>(); Set<String> actualIds = new HashSet<String>();
for (BundleEntry ele : actual.getEntries()) { for (BundleEntry ele : actual.getEntry()) {
actualIds.add(ele.getResource().getId().getIdPart()); actualIds.add(ele.getResource().getId().getIdPart());
} }
assertEquals("Expects to retrieve the 1 orgination matching on Org1's profiles", expectedIds, actualIds); assertEquals("Expects to retrieve the 1 orgination matching on Org1's profiles", expectedIds, actualIds);
@ -1791,7 +1861,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
expectedIds.add(o1id.getIdPart()); expectedIds.add(o1id.getIdPart());
expectedIds.add(o2id.getIdPart()); expectedIds.add(o2id.getIdPart());
actualIds = new HashSet<String>(); actualIds = new HashSet<String>();
for (BundleEntry ele : actual.getEntries()) { for (BundleEntry ele : actual.getEntry()) {
actualIds.add(ele.getResource().getId().getIdPart()); actualIds.add(ele.getResource().getId().getIdPart());
} }
assertEquals("Expects to retrieve the 2 orginations, since we match on (the common profile AND (Org1's second profile OR org2's second profile))", expectedIds, actualIds); assertEquals("Expects to retrieve the 2 orginations, since we match on (the common profile AND (Org1's second profile OR org2's second profile))", expectedIds, actualIds);
@ -1958,14 +2028,14 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.execute(); .execute();
//@formatter:on //@formatter:on
assertEquals(2, found.size()); assertEquals(2, found.getEntry().size());
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass()); assertEquals(Patient.class, found.getEntry().get(0).getResource().getClass());
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum()); assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntry().get(0).getSearchMode().getValueAsEnum());
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE)); assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntry().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString("<table class=\"hapiPropertyTable")); assertThat(found.getEntry().get(0).getResource().getText().getDiv().getValueAsString(), containsString("<table class=\"hapiPropertyTable"));
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass()); assertEquals(Organization.class, found.getEntry().get(1).getResource().getClass());
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getSearchMode().getValueAsEnum()); assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntry().get(1).getSearchMode().getValueAsEnum());
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE)); assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntry().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
} }
@Test(expected = InvalidRequestException.class) @Test(expected = InvalidRequestException.class)
@ -2405,8 +2475,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history")); assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history"));
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2")).encodedJson().prettyPrint().execute(); Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2")).encodedJson().prettyPrint().execute();
assertEquals(1, actual.size()); assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
} }

View File

@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.api.server;
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -29,25 +29,17 @@ import ca.uhn.fhir.parser.IParser;
/** /**
* @author Peter Van Houte * @author Peter Van Houte
* *
* @param <T> A functional class that parses an outcome * @param <T>
* A functional class that parses an outcome
*/ */
public abstract class ParseAction<T> { public abstract class ParseAction<T> {
protected T theOutcome; protected T theOutcome;
protected ParseAction(T outcome) {
this.theOutcome = outcome;
}
public abstract void execute(IParser parser, Writer writer) throws IOException; protected ParseAction(T outcome) {
this.theOutcome = outcome;
}
public abstract void execute(IParser parser, Writer writer) throws IOException;
public static ParseAction<TagList> create(TagList outcome) {
return outcome == null ? null : new ParseAction<TagList>(outcome) {
@Override
public void execute(IParser theParser, Writer theWriter) throws IOException {
theParser.encodeTagListToWriter(this.theOutcome, theWriter);
}
};
}
} }

View File

@ -21,9 +21,7 @@ package ca.uhn.fhir.rest.server.interceptor;
*/ */
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -33,12 +31,9 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.rest.annotation.Read; import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
@ -179,48 +174,6 @@ public interface IServerInterceptor {
*/ */
boolean outgoingResponse(RequestDetails theRequestDetails); boolean outgoingResponse(RequestDetails theRequestDetails);
/**
* This method is called after the server implementation method has been called, but before any attempt to stream the
* response back to the client
*
* @param theRequestDetails
* A bean containing details about the request that is about to be processed, including
* @param theResponseObject
* The actual object which is being streamed to the client as a response
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
* will be called.
* @throws AuthenticationException
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean outgoingResponse(RequestDetails theRequest, Bundle theResponseObject);
/**
* This method is called after the server implementation method has been called, but before any attempt to stream the
* response back to the client
*
* @param theRequestDetails
* A bean containing details about the request that is about to be processed, including
* @param theResponseObject
* The actual object which is being streamed to the client as a response
* @param theServletRequest
* The incoming request
* @param theServletResponse
* The response. Note that interceptors may choose to provide a response (i.e. by calling
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
* to indicate that the server itself should not also provide a response.
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
* must return <code>false</code>. In this case, no further processing will occur and no further interceptors
* will be called.
* @throws AuthenticationException
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
/** /**
* This method is called after the server implementation method has been called, but before any attempt to stream the * This method is called after the server implementation method has been called, but before any attempt to stream the
* response back to the client * response back to the client
@ -366,9 +319,10 @@ public interface IServerInterceptor {
* This method is called after all processing is completed for a request, but only if the * This method is called after all processing is completed for a request, but only if the
* request completes normally (i.e. no exception is thrown). * request completes normally (i.e. no exception is thrown).
* <p> * <p>
* Note that this individual interceptors will have this method called in the reverse order from the order in * Note that this individual interceptors will have this method called in the reverse order from the order in
* which the interceptors were registered with the server. * which the interceptors were registered with the server.
* </p> * </p>
*
* @param theRequestDetails * @param theRequestDetails
* The request itself * The request itself
*/ */

View File

@ -28,7 +28,6 @@ import javax.servlet.http.HttpServletResponse;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
@ -69,18 +68,6 @@ public class InterceptorAdapter implements IServerInterceptor {
return outgoingResponse(theRequestDetails, details.getServletRequest(), details.getServletResponse()); return outgoingResponse(theRequestDetails, details.getServletRequest(), details.getServletResponse());
} }
@Override
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle bundle) {
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
return outgoingResponse(details, bundle, details.getServletRequest(), details.getServletResponse());
}
@Override
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
throws AuthenticationException {
return true;
}
@Override @Override
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException { public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
return true; return true;

View File

@ -22,9 +22,7 @@ package ca.uhn.fhir.rest.server.interceptor.auth;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -32,19 +30,15 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException; import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
import ca.uhn.fhir.rest.server.interceptor.*; import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
/** /**
@ -244,19 +238,6 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
applyRulesAndFailIfDeny(theOperation, requestDetails, inputResource, inputResourceId, null); applyRulesAndFailIfDeny(theOperation, requestDetails, inputResource, inputResourceId, null);
} }
@Override
@CoverageIgnore
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theBundle) {
throw failForDstu1();
}
@Override
@CoverageIgnore
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
throws AuthenticationException {
throw failForDstu1();
}
@Override @Override
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) { public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) { switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) {
@ -365,7 +346,10 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
} }
private enum OperationExamineDirection { private enum OperationExamineDirection {
BOTH, IN, NONE, OUT, BOTH,
IN,
NONE,
OUT,
} }
public static class Verdict { public static class Verdict {

View File

@ -21,17 +21,10 @@ package ca.uhn.fhir.rest.server.method;
*/ */
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.IOException; import java.io.*;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
@ -39,48 +32,15 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.model.api.*;
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.TagList;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.AddTags; import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.Create; import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.annotation.Delete; import ca.uhn.fhir.rest.api.server.*;
import ca.uhn.fhir.rest.annotation.DeleteTags;
import ca.uhn.fhir.rest.annotation.GetPage;
import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.Patch;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException; import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.server.BundleProviders; import ca.uhn.fhir.rest.server.*;
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider; import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
@ -379,7 +339,6 @@ public abstract class BaseMethodBinding<T> {
Delete delete = theMethod.getAnnotation(Delete.class); Delete delete = theMethod.getAnnotation(Delete.class);
History history = theMethod.getAnnotation(History.class); History history = theMethod.getAnnotation(History.class);
Validate validate = theMethod.getAnnotation(Validate.class); Validate validate = theMethod.getAnnotation(Validate.class);
GetTags getTags = theMethod.getAnnotation(GetTags.class);
AddTags addTags = theMethod.getAnnotation(AddTags.class); AddTags addTags = theMethod.getAnnotation(AddTags.class);
DeleteTags deleteTags = theMethod.getAnnotation(DeleteTags.class); DeleteTags deleteTags = theMethod.getAnnotation(DeleteTags.class);
Transaction transaction = theMethod.getAnnotation(Transaction.class); Transaction transaction = theMethod.getAnnotation(Transaction.class);
@ -388,7 +347,7 @@ public abstract class BaseMethodBinding<T> {
Patch patch = theMethod.getAnnotation(Patch.class); Patch patch = theMethod.getAnnotation(Patch.class);
// ** if you add another annotation above, also add it to the next line: // ** if you add another annotation above, also add it to the next line:
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, getTags, addTags, deleteTags, transaction, operation, getPage, patch)) { if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, addTags, deleteTags, transaction, operation, getPage, patch)) {
return null; return null;
} }
@ -408,17 +367,10 @@ public abstract class BaseMethodBinding<T> {
} }
Class<?> returnTypeFromMethod = theMethod.getReturnType(); Class<?> returnTypeFromMethod = theMethod.getReturnType();
if (getTags != null) { if (MethodOutcome.class.isAssignableFrom(returnTypeFromMethod)) {
if (!TagList.class.equals(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @"
+ GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
}
} else if (MethodOutcome.class.isAssignableFrom(returnTypeFromMethod)) {
// returns a method outcome // returns a method outcome
} else if (IBundleProvider.class.equals(returnTypeFromMethod)) { } else if (IBundleProvider.class.equals(returnTypeFromMethod)) {
// returns a bundle provider // returns a bundle provider
} else if (Bundle.class.equals(returnTypeFromMethod)) {
// returns a bundle
} else if (void.class.equals(returnTypeFromMethod)) { } else if (void.class.equals(returnTypeFromMethod)) {
// returns a bundle // returns a bundle
} else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) { } else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
@ -433,7 +385,7 @@ public abstract class BaseMethodBinding<T> {
} else { } else {
if (!isResourceInterface(returnTypeFromMethod) && !verifyIsValidResourceReturnType(returnTypeFromMethod)) { if (!isResourceInterface(returnTypeFromMethod) && !verifyIsValidResourceReturnType(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
+ " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", " + IBundleProvider.class.getSimpleName() + " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, Bundle, " + IBundleProvider.class.getSimpleName()
+ ", etc., see the documentation for more details)"); + ", etc., see the documentation for more details)");
} }
} }
@ -455,8 +407,6 @@ public abstract class BaseMethodBinding<T> {
returnTypeFromAnnotation = update.type(); returnTypeFromAnnotation = update.type();
} else if (validate != null) { } else if (validate != null) {
returnTypeFromAnnotation = validate.type(); returnTypeFromAnnotation = validate.type();
} else if (getTags != null) {
returnTypeFromAnnotation = getTags.type();
} else if (addTags != null) { } else if (addTags != null) {
returnTypeFromAnnotation = addTags.type(); returnTypeFromAnnotation = addTags.type();
} else if (deleteTags != null) { } else if (deleteTags != null) {
@ -520,8 +470,6 @@ public abstract class BaseMethodBinding<T> {
return new HistoryMethodBinding(theMethod, theContext, theProvider); return new HistoryMethodBinding(theMethod, theContext, theProvider);
} else if (validate != null) { } else if (validate != null) {
return new ValidateMethodBindingDstu2Plus(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate); return new ValidateMethodBindingDstu2Plus(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
} else if (getTags != null) {
return new GetTagsMethodBinding(theMethod, theContext, theProvider, getTags);
} else if (addTags != null) { } else if (addTags != null) {
return new AddTagsMethodBinding(theMethod, theContext, theProvider, addTags); return new AddTagsMethodBinding(theMethod, theContext, theProvider, addTags);
} else if (deleteTags != null) { } else if (deleteTags != null) {

View File

@ -32,7 +32,8 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.*; 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;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.api.*; import ca.uhn.fhir.rest.api.*;
@ -91,8 +92,6 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
} else { } else {
myMethodReturnType = MethodReturnTypeEnum.RESOURCE; myMethodReturnType = MethodReturnTypeEnum.RESOURCE;
} }
} else if (Bundle.class.isAssignableFrom(methodReturnType)) {
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
} else if (IBundleProvider.class.isAssignableFrom(methodReturnType)) { } else if (IBundleProvider.class.isAssignableFrom(methodReturnType)) {
myMethodReturnType = MethodReturnTypeEnum.BUNDLE_PROVIDER; myMethodReturnType = MethodReturnTypeEnum.BUNDLE_PROVIDER;
} else if (MethodOutcome.class.isAssignableFrom(methodReturnType)) { } else if (MethodOutcome.class.isAssignableFrom(methodReturnType)) {

View File

@ -1,131 +0,0 @@
package ca.uhn.fhir.rest.server.method;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 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.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.ParseAction;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
private Integer myIdParamIndex;
private String myResourceName;
private Class<? extends IBaseResource> myType;
private Integer myVersionIdParamIndex;
public GetTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, GetTags theAnnotation) {
super(theMethod, theContext, theProvider);
if (theProvider instanceof IResourceProvider) {
myType = ((IResourceProvider) theProvider).getResourceType();
} else {
myType = theAnnotation.type();
}
if (!Modifier.isInterface(myType.getModifiers())) {
myResourceName = theContext.getResourceDefinition(myType).getName();
}
myIdParamIndex = ParameterUtil.findIdParameterIndex(theMethod, getContext());
myVersionIdParamIndex = ParameterUtil.findVersionIdParameterIndex(theMethod);
if (myIdParamIndex != null && myType.equals(IResource.class)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not specify a resource type, but has an @" + IdParam.class.getSimpleName()
+ " parameter. Please specity a resource type in the @" + GetTags.class.getSimpleName() + " annotation");
}
}
@Override
public String getResourceName() {
return myResourceName;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.GET_TAGS;
}
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() != RequestTypeEnum.GET) {
return false;
}
if (!Constants.PARAM_TAGS.equals(theRequest.getOperation())) {
return false;
}
if (myResourceName == null) {
if (getResourceName() != null) {
return false;
}
} else if (!myResourceName.equals(theRequest.getResourceName())) {
return false;
}
if ((myIdParamIndex != null) != (theRequest.getId() != null)) {
return false;
}
return true;
}
@Override
public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
Object[] params = createParametersForServerRequest(theRequest);
if (myIdParamIndex != null) {
params[myIdParamIndex] = theRequest.getId();
}
if (myVersionIdParamIndex != null) {
params[myVersionIdParamIndex] = theRequest.getId();
}
TagList resp = (TagList) invokeServerMethod(theServer, theRequest, params);
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
IServerInterceptor next = theServer.getInterceptors().get(i);
boolean continueProcessing = next.outgoingResponse(theRequest, resp);
if (!continueProcessing) {
return null;
}
}
return theRequest.getResponse().returnResponse(ParseAction.create(resp), Constants.STATUS_HTTP_200_OK, false, null, null);
}
}

View File

@ -26,27 +26,19 @@ import java.io.IOException;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; 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.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.*;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ParameterUtil; import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
@ -54,7 +46,6 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetai
public class OperationMethodBinding extends BaseResourceReturningMethodBinding { public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationMethodBinding.class);
private BundleTypeEnum myBundleType; private BundleTypeEnum myBundleType;
private boolean myCanOperateAtInstanceLevel; private boolean myCanOperateAtInstanceLevel;
private boolean myCanOperateAtServerLevel; private boolean myCanOperateAtServerLevel;
@ -115,11 +106,6 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
} }
} }
if (theMethod.getReturnType().isAssignableFrom(Bundle.class)) {
throw new ConfigurationException("Can not return a DSTU1 bundle from an @" + Operation.class.getSimpleName() + " method. Found in method " + theMethod.getName() + " defined in type "
+ theMethod.getDeclaringClass().getName());
}
if (theMethod.getReturnType().equals(IBundleProvider.class)) { if (theMethod.getReturnType().equals(IBundleProvider.class)) {
myReturnType = ReturnTypeEnum.BUNDLE; myReturnType = ReturnTypeEnum.BUNDLE;
} else { } else {

View File

@ -29,7 +29,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome; import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
@ -39,9 +38,7 @@ import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.TransactionParam; import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.*;
import ca.uhn.fhir.rest.api.server.IRestfulServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
@ -122,11 +119,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
// Grab the IDs of all of the resources in the transaction // Grab the IDs of all of the resources in the transaction
List<IResource> resources; List<IResource> resources;
if (theMethodParams[myTransactionParamIndex] instanceof Bundle) { resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
} else {
resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
}
IdentityHashMap<IResource, IdDt> oldIds = new IdentityHashMap<IResource, IdDt>(); IdentityHashMap<IResource, IdDt> oldIds = new IdentityHashMap<IResource, IdDt>();
for (IResource next : resources) { for (IResource next : resources) {

View File

@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server.method;
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -23,18 +23,14 @@ package ca.uhn.fhir.rest.server.method;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.TransactionParam; import ca.uhn.fhir.rest.annotation.TransactionParam;
@ -43,33 +39,31 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.BundleUtil;
public class TransactionParameter implements IParameter { public class TransactionParameter implements IParameter {
// private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionParameter.class); // private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionParameter.class);
private FhirContext myContext; private FhirContext myContext;
private ParamStyle myParamStyle; private ParamStyle myParamStyle;
private Class<? extends IBaseResource> myResourceBundleType; private Class<? extends IBaseResource> myResourceBundleType;
public TransactionParameter(FhirContext theContext) { public TransactionParameter(FhirContext theContext) {
myContext = theContext; myContext = theContext;
} }
private String createParameterTypeError(Method theMethod) { private String createParameterTypeError(Method theMethod) {
return "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName() + "> or Bundle"; return "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName()
+ " but is not of type List<" + IResource.class.getCanonicalName() + "> or Bundle";
} }
@Override @Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) { public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
if (theOuterCollectionType != null) { if (theOuterCollectionType != null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but can not be a collection of collections"); throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @"
+ TransactionParam.class.getName() + " but can not be a collection of collections");
} }
if (theParameterType.equals(Bundle.class)) { if (Modifier.isInterface(theParameterType.getModifiers()) == false && IBaseResource.class.isAssignableFrom(theParameterType)) {
myParamStyle = ParamStyle.DSTU1_BUNDLE;
if (theInnerCollectionType != null) {
throw new ConfigurationException(createParameterTypeError(theMethod));
}
} else if (Modifier.isInterface(theParameterType.getModifiers()) == false && IBaseResource.class.isAssignableFrom(theParameterType)) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<? extends IBaseResource> parameterType = (Class<? extends IBaseResource>) theParameterType; Class<? extends IBaseResource> parameterType = (Class<? extends IBaseResource>) theParameterType;
RuntimeResourceDefinition def = myContext.getResourceDefinition(parameterType); RuntimeResourceDefinition def = myContext.getResourceDefinition(parameterType);
@ -90,7 +84,6 @@ public class TransactionParameter implements IParameter {
} }
} }
@Override @Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException { public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
// TODO: don't use a default encoding, just fail! // TODO: don't use a default encoding, just fail!
@ -98,34 +91,25 @@ public class TransactionParameter implements IParameter {
IParser parser = encoding.newParser(theRequest.getServer().getFhirContext()); IParser parser = encoding.newParser(theRequest.getServer().getFhirContext());
Reader reader; Reader reader = ResourceParameter.createRequestReader(theRequest);
reader = ResourceParameter.createRequestReader(theRequest); try {
switch (myParamStyle) { switch (myParamStyle) {
case DSTU1_BUNDLE: {
Bundle bundle;
bundle = parser.parseBundle(reader);
//FIXME resource leak
return bundle;
}
case RESOURCE_LIST: { case RESOURCE_LIST: {
Bundle bundle = parser.parseBundle(reader); Class<? extends IBaseResource> type = myContext.getResourceDefinition("Bundle").getImplementingClass();
ArrayList<IResource> resourceList = new ArrayList<IResource>(); IBaseResource bundle = parser.parseResource(type, reader);
for (BundleEntry next : bundle.getEntries()) { List<IBaseResource> resourceList = BundleUtil.toListOfResources(myContext, (IBaseBundle) bundle);
if (next.getResource() != null) {
resourceList.add(next.getResource());
}
}
//FIXME resource leak
return resourceList; return resourceList;
} }
case RESOURCE_BUNDLE: case RESOURCE_BUNDLE:
//FIXME resource leak
return parser.parseResource(myResourceBundleType, reader); return parser.parseResource(myResourceBundleType, reader);
} }
//FIXME resource leak throw new IllegalStateException("Unknown type: " + myParamStyle); // should not happen
throw new IllegalStateException("Unknown type: " + myParamStyle); // should not happen
} finally {
IOUtils.closeQuietly(reader);
}
} }
public ParamStyle getParamStyle() { public ParamStyle getParamStyle() {
@ -133,8 +117,6 @@ public class TransactionParameter implements IParameter {
} }
public enum ParamStyle { public enum ParamStyle {
/** Old style bundle (defined in hapi-fhir-base) */
DSTU1_BUNDLE,
/** New style bundle (defined in hapi-fhir-structures-* as a resource definition itself */ /** New style bundle (defined in hapi-fhir-structures-* as a resource definition itself */
RESOURCE_BUNDLE, RESOURCE_BUNDLE,
/** List of resources */ /** List of resources */