Implement meta operations in client
This commit is contained in:
parent
c22aa14d29
commit
350028be73
|
@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.client;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -40,6 +41,7 @@ import org.apache.http.client.methods.HttpRequestBase;
|
|||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -86,6 +88,10 @@ import ca.uhn.fhir.rest.gclient.IGetTags;
|
|||
import ca.uhn.fhir.rest.gclient.IHistory;
|
||||
import ca.uhn.fhir.rest.gclient.IHistoryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IHistoryUntyped;
|
||||
import ca.uhn.fhir.rest.gclient.IMeta;
|
||||
import ca.uhn.fhir.rest.gclient.IMetaAddOrDeleteSourced;
|
||||
import ca.uhn.fhir.rest.gclient.IMetaAddOrDeleteUnsourced;
|
||||
import ca.uhn.fhir.rest.gclient.IMetaGetUnsourced;
|
||||
import ca.uhn.fhir.rest.gclient.IOperation;
|
||||
import ca.uhn.fhir.rest.gclient.IOperationUnnamed;
|
||||
import ca.uhn.fhir.rest.gclient.IOperationUntyped;
|
||||
|
@ -130,6 +136,7 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.util.ICallable;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
@ -702,7 +709,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
addPreferHeader(myPrefer, invocation);
|
||||
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
|
@ -1247,7 +1254,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type: " + theOutputParameterType.getName());
|
||||
}
|
||||
if (!"Parameters".equals(def.getName())) {
|
||||
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type for a resource named " + "Parameters" + " - " + theOutputParameterType.getName() + " is a resource named: " + def.getName());
|
||||
throw new IllegalArgumentException("theOutputParameterType must refer to a HAPI FHIR Resource type for a resource named " + "Parameters" + " - " + theOutputParameterType.getName()
|
||||
+ " is a resource named: " + def.getName());
|
||||
}
|
||||
myParameters = (IBaseParameters) def.newInstance();
|
||||
return this;
|
||||
|
@ -1266,7 +1274,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private final class OperationOutcomeResponseHandler implements IClientResponseHandler<BaseOperationOutcome> {
|
||||
|
||||
@Override
|
||||
public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
|
||||
public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders)
|
||||
throws BaseServerResponseException {
|
||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (respType == null) {
|
||||
return null;
|
||||
|
@ -1473,6 +1482,42 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
}
|
||||
|
||||
private final class MetaParametersResponseHandler<T extends IBaseMetaType> implements IClientResponseHandler<T> {
|
||||
|
||||
private Class<T> myType;
|
||||
|
||||
public MetaParametersResponseHandler(Class<T> theMetaType) {
|
||||
myType = theMetaType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T 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);
|
||||
RuntimeResourceDefinition type = myContext.getResourceDefinition("Parameters");
|
||||
IBaseResource retVal = parser.parseResource(type.getImplementingClass(), theResponseReader);
|
||||
|
||||
BaseRuntimeChildDefinition paramChild = type.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
List<IBase> parameter = paramChild.getAccessor().getValues(retVal);
|
||||
if (parameter == null || parameter.isEmpty()) {
|
||||
return (T) myContext.getElementDefinition(myType).newInstance();
|
||||
}
|
||||
IBase param = parameter.get(0);
|
||||
|
||||
List<IBase> meta = paramChildElem.getChildByName("value[x]").getAccessor().getValues(param);
|
||||
if (meta.isEmpty()) {
|
||||
return (T) myContext.getElementDefinition(myType).newInstance();
|
||||
}
|
||||
return (T) meta.get(0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private class SearchInternal extends BaseClientExecutable<IQuery<Object>, Object> implements IQuery<Object>, IUntypedQuery {
|
||||
|
||||
|
@ -1526,7 +1571,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
if (myParamLimit != null) {
|
||||
addParam(params, Constants.PARAM_COUNT, Integer.toString(myParamLimit));
|
||||
}
|
||||
|
||||
|
||||
if (myLastUpdated != null) {
|
||||
for (DateParam next : myLastUpdated.getValuesAsQueryTokens()) {
|
||||
addParam(params, Constants.PARAM_LASTUPDATED, next.getValueAsQueryToken());
|
||||
|
@ -1534,7 +1579,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
if (myReturnBundleType == null && myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
throw new IllegalArgumentException("When using the client with HL7.org structures, you must specify " + "the bundle return type for the client by adding \".returnBundle(org.hl7.fhir.instance.model.Bundle.class)\" to your search method call before the \".execute()\" method");
|
||||
throw new IllegalArgumentException("When using the client with HL7.org structures, you must specify "
|
||||
+ "the bundle return type for the client by adding \".returnBundle(org.hl7.fhir.instance.model.Bundle.class)\" to your search method call before the \".execute()\" method");
|
||||
}
|
||||
|
||||
IClientResponseHandler<? extends IBase> binding;
|
||||
|
@ -1852,7 +1898,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
addPreferHeader(myPrefer, invocation);
|
||||
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
|
@ -1939,9 +1985,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
public IValidateUntyped resource(String theResourceRaw) {
|
||||
Validate.notBlank(theResourceRaw, "theResourceRaw must not be null or blank");
|
||||
myResource = parseResourceBody(theResourceRaw);
|
||||
|
||||
|
||||
EncodingEnum enc = MethodUtil.detectEncodingNoDefault(theResourceRaw);
|
||||
if (enc==null) {
|
||||
if (enc == null) {
|
||||
throw new IllegalArgumentException("Could not detect encoding (XML/JSON) in string. Is this a valid FHIR resource?");
|
||||
}
|
||||
switch (enc) {
|
||||
|
@ -1957,4 +2003,124 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private class MetaInternal extends BaseClientExecutable implements IMeta, IMetaAddOrDeleteUnsourced, IMetaGetUnsourced, IMetaAddOrDeleteSourced {
|
||||
|
||||
private MetaOperation myOperation;
|
||||
private String myOnType;
|
||||
private IIdType myId;
|
||||
private Class<? extends IBaseMetaType> myMetaType;
|
||||
private IBaseMetaType myMeta;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object execute() {
|
||||
|
||||
BaseHttpClientInvocation invocation = null;
|
||||
|
||||
IBaseParameters parameters = ParametersUtil.newInstance(myContext);
|
||||
switch (myOperation) {
|
||||
case ADD:
|
||||
ParametersUtil.addParameterToParameters(myContext, parameters, myMeta, "meta");
|
||||
invocation = OperationMethodBinding.createOperationInvocation(myContext, myId.getResourceType(), myId.getIdPart(), "$meta-add", parameters, false);
|
||||
break;
|
||||
case DELETE:
|
||||
ParametersUtil.addParameterToParameters(myContext, parameters, myMeta, "meta");
|
||||
invocation = OperationMethodBinding.createOperationInvocation(myContext, myId.getResourceType(), myId.getIdPart(), "$meta-delete", parameters, false);
|
||||
break;
|
||||
case GET:
|
||||
if (myId != null) {
|
||||
invocation = OperationMethodBinding.createOperationInvocation(myContext, myOnType, myId.getIdPart(), "$meta", parameters, true);
|
||||
} else if (myOnType != null) {
|
||||
invocation = OperationMethodBinding.createOperationInvocation(myContext, myOnType, null, "$meta", parameters, true);
|
||||
} else {
|
||||
invocation = OperationMethodBinding.createOperationInvocation(myContext, null, null, "$meta", parameters, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Should not happen
|
||||
if (invocation == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
IClientResponseHandler handler;
|
||||
handler = new MetaParametersResponseHandler(myMetaType);
|
||||
return invoke(null, handler, invocation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseMetaType> IMetaGetUnsourced<T> get(Class<T> theType) {
|
||||
myMetaType = theType;
|
||||
myOperation = MetaOperation.GET;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMetaAddOrDeleteUnsourced add() {
|
||||
myOperation = MetaOperation.ADD;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMetaAddOrDeleteUnsourced delete() {
|
||||
myOperation = MetaOperation.DELETE;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClientExecutable fromServer() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClientExecutable fromType(String theResourceName) {
|
||||
Validate.notBlank(theResourceName, "theResourceName must not be blank");
|
||||
myOnType = theResourceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClientExecutable fromResource(IIdType theId) {
|
||||
setIdInternal(theId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMetaAddOrDeleteSourced onResource(IIdType theId) {
|
||||
setIdInternal(theId);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void setIdInternal(IIdType theId) {
|
||||
Validate.notBlank(theId.getResourceType(), "theId must contain a resource type");
|
||||
Validate.notBlank(theId.getIdPart(), "theId must contain an ID part");
|
||||
myOnType = theId.getResourceType();
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseMetaType> IClientExecutable<IClientExecutable<?, ?>, T> meta(T theMeta) {
|
||||
Validate.notNull(theMeta, "theMeta must not be null");
|
||||
myMeta = theMeta;
|
||||
myMetaType = myMeta.getClass();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private enum MetaOperation {
|
||||
DELETE, ADD, GET
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMeta meta() {
|
||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
throw new IllegalStateException("Can not call $meta operations on a DSTU1 client");
|
||||
}
|
||||
return new MetaInternal();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
|
|||
import ca.uhn.fhir.rest.gclient.IGetPage;
|
||||
import ca.uhn.fhir.rest.gclient.IGetTags;
|
||||
import ca.uhn.fhir.rest.gclient.IHistory;
|
||||
import ca.uhn.fhir.rest.gclient.IMeta;
|
||||
import ca.uhn.fhir.rest.gclient.IOperation;
|
||||
import ca.uhn.fhir.rest.gclient.IRead;
|
||||
import ca.uhn.fhir.rest.gclient.ITransaction;
|
||||
|
@ -69,6 +70,14 @@ public interface IGenericClient extends IRestfulClient {
|
|||
*/
|
||||
ICreate create();
|
||||
|
||||
/**
|
||||
* Fluent method for the "meta" operations, which can be used to get, add and remove tags and other
|
||||
* Meta elements from a resource or across the server.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
IMeta meta();
|
||||
|
||||
/**
|
||||
* Implementation of the "type create" method.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IMeta {
|
||||
|
||||
/**
|
||||
* Fetch the current metadata
|
||||
*
|
||||
* @param theMetaType The type of the meta datatype for the given FHIR model version (should be <code>MetaDt.class</code> or <code>MetaType.class</code>)
|
||||
*/
|
||||
<T extends IBaseMetaType> IMetaGetUnsourced<T> get(Class<T> theMetaType);
|
||||
|
||||
/**
|
||||
* Add the elements in the given metadata to the already existing set (do not remove any)
|
||||
*/
|
||||
IMetaAddOrDeleteUnsourced add();
|
||||
|
||||
/**
|
||||
* Delete the elements in the given metadata to the
|
||||
*/
|
||||
IMetaAddOrDeleteUnsourced delete();
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
|
||||
public interface IMetaAddOrDeleteSourced {
|
||||
|
||||
<T extends IBaseMetaType> IClientExecutable<IClientExecutable<?, ?>, T> meta(T theMeta);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
public interface IMetaAddOrDeleteUnsourced {
|
||||
|
||||
IMetaAddOrDeleteSourced onResource(IIdType theId);
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
public interface IMetaGetUnsourced<T extends IBaseMetaType> {
|
||||
|
||||
IClientExecutable<IClientExecutable<?,?>, T> fromServer();
|
||||
|
||||
IClientExecutable<IClientExecutable<?,?>, T> fromType(String theResourceName);
|
||||
|
||||
/**
|
||||
* Get the meta from a resource instance by ID.
|
||||
*
|
||||
* @param theId The ID. Must contain both a resource type and an ID part
|
||||
*/
|
||||
IClientExecutable<IClientExecutable<?,?>, T> fromResource(IIdType theId);
|
||||
|
||||
|
||||
}
|
|
@ -27,7 +27,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
|
@ -35,12 +34,10 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildPrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||
|
@ -48,6 +45,7 @@ import ca.uhn.fhir.rest.param.ResourceParameter;
|
|||
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.util.ParametersUtil;
|
||||
|
||||
public class OperationParameter implements IParameter {
|
||||
|
||||
|
@ -72,35 +70,7 @@ public class OperationParameter implements IParameter {
|
|||
myMax = theMax;
|
||||
}
|
||||
|
||||
private static void addClientParameter(FhirContext theContext, Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) {
|
||||
if (theSourceClientArgument instanceof IBaseResource) {
|
||||
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName);
|
||||
paramChildElem.getChildByName("resource").getMutator().addValue(parameter, (IBaseResource) theSourceClientArgument);
|
||||
} else if (theSourceClientArgument instanceof IBaseDatatype) {
|
||||
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName);
|
||||
paramChildElem.getChildByName("value[x]").getMutator().addValue(parameter, (IBaseDatatype) theSourceClientArgument);
|
||||
} else if (theSourceClientArgument instanceof Collection) {
|
||||
Collection<?> collection = (Collection<?>) theSourceClientArgument;
|
||||
for (Object next : collection) {
|
||||
addClientParameter(theContext, next, theTargetResource, paramChild, paramChildElem, theName);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Don't know how to handle value of type " + theSourceClientArgument.getClass() + " for paramater " + theName);
|
||||
}
|
||||
}
|
||||
|
||||
private static IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) {
|
||||
IBase parameter = paramChildElem.newInstance();
|
||||
paramChild.getMutator().addValue(theTargetResource, parameter);
|
||||
IPrimitiveType<?> value;
|
||||
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
value = (IPrimitiveType<?>) theContext.getElementDefinition("string").newInstance(theName);
|
||||
} else {
|
||||
value = new StringDt(theName);
|
||||
}
|
||||
paramChildElem.getChildByName("name").getMutator().addValue(parameter, value);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return myMax;
|
||||
|
@ -145,15 +115,7 @@ public class OperationParameter implements IParameter {
|
|||
sourceClientArgument = myConverter.outgoingClient(sourceClientArgument);
|
||||
}
|
||||
|
||||
addParameterToParameters(theContext, theTargetResource, sourceClientArgument, myName);
|
||||
}
|
||||
|
||||
public static void addParameterToParameters(FhirContext theContext, IBaseResource theTargetResource, Object sourceClientArgument, String theName) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
|
||||
addClientParameter(theContext, sourceClientArgument, theTargetResource, paramChild, paramChildElem, theName);
|
||||
ParametersUtil.addParameterToParameters(theContext, theTargetResource, sourceClientArgument, myName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -33,6 +33,7 @@ import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
|||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
|
||||
public class ValidateMethodBindingDstu2 extends OperationMethodBinding {
|
||||
|
||||
|
@ -68,7 +69,7 @@ public class ValidateMethodBindingDstu2 extends OperationMethodBinding {
|
|||
|
||||
public static BaseHttpClientInvocation createValidateInvocation(FhirContext theContext, IBaseResource theResource) {
|
||||
IBaseParameters parameters = (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||
OperationParameter.addParameterToParameters(theContext, parameters, theResource, "resource");
|
||||
ParametersUtil.addParameterToParameters(theContext, parameters, theResource, "resource");
|
||||
|
||||
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||
String resourceId = theResource.getIdElement().getIdPart();
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
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.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with parameters resources
|
||||
*/
|
||||
public class ParametersUtil {
|
||||
|
||||
public static void addParameterToParameters(FhirContext theContext, IBaseResource theTargetResource, Object sourceClientArgument, String theName) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theTargetResource);
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
|
||||
addClientParameter(theContext, sourceClientArgument, theTargetResource, paramChild, paramChildElem, theName);
|
||||
}
|
||||
|
||||
private static void addClientParameter(FhirContext theContext, Object theSourceClientArgument, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) {
|
||||
if (theSourceClientArgument instanceof IBaseResource) {
|
||||
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName);
|
||||
paramChildElem.getChildByName("resource").getMutator().addValue(parameter, (IBaseResource) theSourceClientArgument);
|
||||
} else if (theSourceClientArgument instanceof IBaseDatatype) {
|
||||
IBase parameter = createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName);
|
||||
paramChildElem.getChildByName("value[x]").getMutator().addValue(parameter, (IBaseDatatype) theSourceClientArgument);
|
||||
} else if (theSourceClientArgument instanceof Collection) {
|
||||
Collection<?> collection = (Collection<?>) theSourceClientArgument;
|
||||
for (Object next : collection) {
|
||||
addClientParameter(theContext, next, theTargetResource, paramChild, paramChildElem, theName);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Don't know how to handle value of type " + theSourceClientArgument.getClass() + " for paramater " + theName);
|
||||
}
|
||||
}
|
||||
|
||||
private static IBase createParameterRepetition(FhirContext theContext, IBaseResource theTargetResource, BaseRuntimeChildDefinition paramChild, BaseRuntimeElementCompositeDefinition<?> paramChildElem, String theName) {
|
||||
IBase parameter = paramChildElem.newInstance();
|
||||
paramChild.getMutator().addValue(theTargetResource, parameter);
|
||||
IPrimitiveType<?> value;
|
||||
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
value = (IPrimitiveType<?>) theContext.getElementDefinition("string").newInstance(theName);
|
||||
} else {
|
||||
value = new StringDt(theName);
|
||||
}
|
||||
paramChildElem.getChildByName("name").getMutator().addValue(parameter, value);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static IBaseParameters newInstance(FhirContext theContext) {
|
||||
return (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||
}
|
||||
}
|
|
@ -97,7 +97,8 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
//@formatter:on
|
||||
public Parameters meta() {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation());
|
||||
MetaDt metaGetOperation = getDao().metaGetOperation();
|
||||
parameters.addParameter().setName("return").setValue(metaGetOperation);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
@ -108,7 +109,8 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
//@formatter:on
|
||||
public Parameters meta(@IdParam IdDt theId) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaGetOperation(theId));
|
||||
MetaDt metaGetOperation = getDao().metaGetOperation(theId);
|
||||
parameters.addParameter().setName("return").setValue(metaGetOperation);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,8 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||
//@formatter:on
|
||||
public Parameters metaAdd(@IdParam IdDt theId, @OperationParam(name = "meta") MetaDt theMeta) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addParameter().setName("return").setValue(getDao().metaAddOperation(theId, theMeta));
|
||||
MetaDt metaAddOperation = getDao().metaAddOperation(theId, theMeta);
|
||||
parameters.addParameter().setName("return").setValue(metaAddOperation);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
|||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.Device;
|
||||
import ca.uhn.fhir.model.dstu.resource.Practitioner;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
|
@ -184,6 +185,30 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaOperations() throws Exception {
|
||||
String methodName = "testMetaOperations";
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
|
||||
assertEquals(0, meta.getTag().size());
|
||||
|
||||
MetaDt inMeta = new MetaDt();
|
||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
|
||||
assertEquals(1, meta.getTag().size());
|
||||
|
||||
inMeta = new MetaDt();
|
||||
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
|
||||
assertEquals(0, meta.getTag().size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateResourceConditional() throws IOException {
|
||||
String methodName = "testCreateResourceConditional";
|
||||
|
|
|
@ -41,6 +41,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
|
@ -328,6 +329,152 @@ public class GenericClientDstu2Test {
|
|||
idx++;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaAdd() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
MetaDt inMeta = new MetaDt().addProfile("urn:profile:in");
|
||||
|
||||
Parameters outParams = new Parameters();
|
||||
outParams.addParameter().setName("meta").setValue(new MetaDt().addProfile("urn:profile:out"));
|
||||
final String respString = p.encodeResourceToString(outParams);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
MetaDt resp = client
|
||||
.meta()
|
||||
.add()
|
||||
.onResource(new IdDt("Patient/123"))
|
||||
.meta(inMeta)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient/123/$meta-add", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
|
||||
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"meta\"/><valueMeta><profile value=\"urn:profile:in\"/></valueMeta></parameter></Parameters>", extractBody(capt, idx));
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaDelete() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
MetaDt inMeta = new MetaDt().addProfile("urn:profile:in");
|
||||
|
||||
Parameters outParams = new Parameters();
|
||||
outParams.addParameter().setName("meta").setValue(new MetaDt().addProfile("urn:profile:out"));
|
||||
final String respString = p.encodeResourceToString(outParams);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
MetaDt resp = client
|
||||
.meta()
|
||||
.delete()
|
||||
.onResource(new IdDt("Patient/123"))
|
||||
.meta(inMeta)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient/123/$meta-delete", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
|
||||
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"meta\"/><valueMeta><profile value=\"urn:profile:in\"/></valueMeta></parameter></Parameters>", extractBody(capt, idx));
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaGet() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Parameters inParams = new Parameters();
|
||||
inParams.addParameter().setName("meta").setValue(new MetaDt().addProfile("urn:profile:in"));
|
||||
|
||||
Parameters outParams = new Parameters();
|
||||
outParams.addParameter().setName("meta").setValue(new MetaDt().addProfile("urn:profile:out"));
|
||||
final String respString = p.encodeResourceToString(outParams);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
MetaDt resp = client
|
||||
.meta()
|
||||
.get(MetaDt.class)
|
||||
.fromServer()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/$meta", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
|
||||
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
resp = client
|
||||
.meta()
|
||||
.get(MetaDt.class)
|
||||
.fromType("Patient")
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient/$meta", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
|
||||
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
resp = client
|
||||
.meta()
|
||||
.get(MetaDt.class)
|
||||
.fromResource(new IdDt("Patient/123"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient/123/$meta", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
|
||||
assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationAsGetWithInParameters() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
@ -1357,7 +1504,7 @@ public class GenericClientDstu2Test {
|
|||
private OperationOutcome toOo(IBaseOperationOutcome theOperationOutcome) {
|
||||
return (OperationOutcome) theOperationOutcome;
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
|
|
|
@ -32,7 +32,7 @@ import ${import};
|
|||
@DatatypeDef(name="${className}")
|
||||
public class ${className}
|
||||
extends #{if}( ${className}=="ResourceReferenceDt" || ${className}=="IdentifierDt" || ${className}=="CodingDt" || ${className}=='QuantityDt' || ${className}=='HumanNameDt') Base${className} #{else} BaseIdentifiableElement #{end}
|
||||
implements ICompositeDatatype
|
||||
implements ICompositeDatatype#{if}(${className}=="MetaDt"), org.hl7.fhir.instance.model.api.IBaseMetaType #{end}#{if}(${className}=="CodingDt"), org.hl7.fhir.instance.model.api.IBaseCoding #{end}
|
||||
{
|
||||
|
||||
/**
|
||||
|
@ -167,6 +167,13 @@ public class ${className}
|
|||
setUnits(theUnits);
|
||||
}
|
||||
|
||||
#end
|
||||
#if ( ${className} == "MetaDt" )
|
||||
@Override
|
||||
public MetaDt setLastUpdated(Date theHeaderDateValue) {
|
||||
return setLastUpdated(theHeaderDateValue, TemporalPrecisionEnum.SECOND);
|
||||
}
|
||||
|
||||
#end
|
||||
#if ( ${className} == "ResourceReferenceDt" )
|
||||
/**
|
||||
|
|
|
@ -150,6 +150,9 @@
|
|||
Prevent crash when encoding resources with contained resources
|
||||
if the contained resources contained a circular reference to each other
|
||||
</action>
|
||||
<action type="add">
|
||||
Add $meta, $meta-add, and $meta-delete operations to generic client
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.0" date="2015-May-8">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue