More work on cleanup

This commit is contained in:
James 2017-07-31 15:21:30 -04:00
parent b02fbb6804
commit 3fb75aa61a
20 changed files with 1740 additions and 1978 deletions

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.rest.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import ca.uhn.fhir.model.api.IResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
@Retention(RetentionPolicy.RUNTIME)
@ -44,7 +44,7 @@ public @interface Create {
* for client implementations.
*/
// NB: Read, Search (maybe others) share this annotation, so update the javadocs everywhere
Class<? extends IResource> type() default IResource.class;
Class<? extends IBaseResource> type() default IBaseResource.class;
}

View File

@ -2,11 +2,10 @@ package ca.uhn.fhir.rest.gclient;
import static org.apache.commons.lang3.StringUtils.defaultString;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.*;
import org.apache.commons.lang3.ObjectUtils;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
@ -20,7 +19,7 @@ import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
* 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
* 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,
@ -30,14 +29,13 @@ import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
* #L%
*/
/**
* Token parameter type for use in fluent client interfaces
*/
public class TokenClientParam extends BaseClientParam implements IParam {
public class TokenClientParam extends BaseClientParam implements IParam {
private static final String[] EMPTY_STRING_LIST = new String[0];
private String myParamName;
public TokenClientParam(String theParamName) {
@ -51,6 +49,21 @@ public class TokenClientParam extends BaseClientParam implements IParam {
return new TokenCriterion(getParamName(), null, theCode);
}
@Override
public ICriterion<?> codes(Collection<String> theCodes) {
return new TokenCriterion(getParamName(), theCodes);
}
@Override
public ICriterion<?> codes(String... theCodes) {
return new TokenCriterion(getParamName(), convertToList(theCodes));
}
private List<String> convertToList(String[] theValues) {
String[] values = ObjectUtils.defaultIfNull(theValues, EMPTY_STRING_LIST);
return Arrays.asList(values);
}
@Override
public ICriterion<TokenClientParam> identifier(BaseIdentifierDt theIdentifier) {
return new TokenCriterion(getParamName(), theIdentifier.getSystemElement().getValueAsString(), theIdentifier.getValueElement().getValue());
@ -81,33 +94,21 @@ public class TokenClientParam extends BaseClientParam implements IParam {
return new TokenCriterion(getParamName(), defaultString(theSystem), theCode);
}
@Override
public ICriterion<?> systemAndValues(String theSystem, Collection<String> theValues) {
return new TokenCriterion(getParamName(), defaultString(theSystem), theValues);
}
@Override
public ICriterion<?> systemAndValues(String theSystem, String... theValues) {
return new TokenCriterion(getParamName(), defaultString(theSystem), convertToList(theValues));
}
@Override
public ICriterion<?> codes(String... theCodes) {
return new TokenCriterion(getParamName(), convertToList(theCodes));
public ICriterion<?> codings(IBaseCoding... theCodings) {
return new TokenCriterion(getParamName(), theCodings);
}
@Override
public ICriterion<?> codes(Collection<String> theCodes) {
return new TokenCriterion(getParamName(), theCodes);
}
private List<String> convertToList(String[] theValues) {
String[] values = ObjectUtils.defaultIfNull(theValues, EMPTY_STRING_LIST);
return Arrays.asList(values);
}
@Override
public ICriterion<?> systemAndValues(String theSystem, Collection<String> theValues) {
return new TokenCriterion(getParamName(), defaultString(theSystem), theValues);
}
};
};
}
@Override
@ -124,7 +125,7 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* </p>
*/
public ICriterion<TokenClientParam> hasSystemWithAnyCode(String theSystem) {
return new TokenCriterion(getParamName(), theSystem, (String)null);
return new TokenCriterion(getParamName(), theSystem, (String) null);
}
public interface IMatches {
@ -132,28 +133,52 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* Creates a search criterion that matches against the given code, with no code system specified
*
* @param theIdentifier
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> code(String theIdentifier);
/**
* Creates a search criterion that matches a given system with a collection of possible
* Creates a search criterion that matches a given system with a collection of possible
* codes (this will be used to form a comma-separated OR query) with any system value.
* The URL form of this method will create a parameter like
* The URL form of this method will create a parameter like
* <code>parameter=code1,code2</code>
*
* @param theCodes The codes
* @param theCodes
* The codes
*/
ICriterion<?> codes(Collection<String> theCodes);
/**
* Creates a search criterion that matches a given system with a collection of possible
* codes (this will be used to form a comma-separated OR query) with any system value.
* The URL form of this method will create a parameter like
* <code>parameter=code1,code2</code>
*
* @param theCodes
* The codes
*/
ICriterion<?> codes(String... theCodes);
/**
* Creates a search criterion that matches a given system with a collection of possible
* codes (this will be used to form a comma-separated OR query) with the given
* <code>Coding.system</code> and <code>Coding.value</code> values.
* <p>
* The URL form of this method will create a parameter like
* <code>parameter=system1|code1,system2|code2</code>
* </p>
*
* @param theCodings
* The codings
*/
ICriterion<?> codings(IBaseCoding... theCodings);
/**
* Creates a search criterion that matches against the given identifier (system and code if both are present, or whatever is present)
*
* @param theIdentifier
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> identifier(BaseIdentifierDt theIdentifier);
@ -162,7 +187,7 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* Creates a search criterion that matches against the given identifier, with no system specified
*
* @param theIdentifier
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> identifier(String theIdentifier);
@ -172,7 +197,7 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* In the query URL that is generated, identifiers will be joined with a ',' to create an OR query.
*
* @param theIdentifiers
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> identifiers(BaseIdentifierDt... theIdentifiers);
@ -182,18 +207,18 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* In the query URL that is generated, identifiers will be joined with a ',' to create an OR query.
*
* @param theIdentifiers
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> identifiers(List<BaseIdentifierDt> theIdentifiers);
/**
* Creates a search criterion that matches against the given code system and code
*
* @param theSystem
* The code system (should be a URI)
* The code system (should be a URI)
* @param theCode
* The code
* The code
* @return A criterion
*/
ICriterion<TokenClientParam> systemAndCode(String theSystem, String theCode);
@ -202,41 +227,34 @@ public class TokenClientParam extends BaseClientParam implements IParam {
* Creates a search criterion that matches against the given system and identifier
*
* @param theSystem
* The code system (should be a URI)
* The code system (should be a URI)
* @param theIdentifier
* The identifier
* The identifier
* @return A criterion
*/
ICriterion<TokenClientParam> systemAndIdentifier(String theSystem, String theIdentifier);
/**
* Creates a search criterion that matches a given system with a collection of possible
* Creates a search criterion that matches a given system with a collection of possible
* values (this will be used to form a comma-separated OR query)
*
* @param theSystem The system, which will be used with each value
* @param theValues The values
*/
ICriterion<?> systemAndValues(String theSystem, String... theValues);
/**
* Creates a search criterion that matches a given system with a collection of possible
* values (this will be used to form a comma-separated OR query)
*
* @param theSystem The system, which will be used with each value
* @param theValues The values
* @param theSystem
* The system, which will be used with each value
* @param theValues
* The values
*/
public ICriterion<?> systemAndValues(String theSystem, Collection<String> theValues);
/**
* Creates a search criterion that matches a given system with a collection of possible
* codes (this will be used to form a comma-separated OR query) with any system value.
* The URL form of this method will create a parameter like
* <code>parameter=code1,code2</code>
* Creates a search criterion that matches a given system with a collection of possible
* values (this will be used to form a comma-separated OR query)
*
* @param theCodes The codes
* @param theSystem
* The system, which will be used with each value
* @param theValues
* The values
*/
ICriterion<?> codes(String...theCodes);
ICriterion<?> systemAndValues(String theSystem, String... theValues);
}

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.rest.gclient;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.Collection;
@ -27,6 +28,7 @@ import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
@ -89,6 +91,23 @@ class TokenCriterion implements ICriterion<TokenClientParam>, ICriterionInternal
this(theParamName, null, theCodes);
}
public TokenCriterion(String theParamName, IBaseCoding... theCodings) {
myName=theParamName;
StringBuilder b = new StringBuilder();
if (theCodings != null) {
for (IBaseCoding next : theCodings) {
if (isBlank(next.getSystem()) && isBlank(next.getCode())) {
continue;
}
if (b.length() > 0) {
b.append(',');
}
b.append(toValue(next.getSystem(), next.getCode()));
}
}
myValue = b.toString();
}
@Override
public String getParameterValue(FhirContext theContext) {
return myValue;

View File

@ -26,6 +26,7 @@ import java.lang.reflect.Method;
import java.util.*;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*;
@ -39,19 +40,10 @@ import ca.uhn.fhir.util.UrlUtil;
public class ParameterUtil {
private static final Set<Class<?>> BINDABLE_INTEGER_TYPES;
private static final String LABEL = "label=\"";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ParameterUtil.class);
private static final String SCHEME = "scheme=\"";
static {
HashSet<Class<?>> intTypes = new HashSet<Class<?>>();
intTypes.add(IntegerDt.class);
intTypes.add(Integer.class);
BINDABLE_INTEGER_TYPES = Collections.unmodifiableSet(intTypes);
}
@SuppressWarnings("unchecked")
public static <T extends IIdType> T convertIdToType(IIdType value, Class<T> theIdParamType) {
@ -213,23 +205,20 @@ public class ParameterUtil {
}
public static Object fromInteger(Class<?> theType, IntegerDt theArgument) {
if (theType.equals(IntegerDt.class)) {
if (theArgument == null) {
return null;
}
return theArgument;
}
if (theType.equals(Integer.class)) {
if (theArgument == null) {
return null;
}
return theArgument.getValue();
}
throw new IllegalArgumentException("Invalid Integer type:" + theType);
IPrimitiveType<?> retVal = (IPrimitiveType<?>) ReflectionUtil.newInstance(theType);
retVal.setValueAsString(theArgument.getValueAsString());
return retVal;
}
public static Set<Class<?>> getBindableIntegerTypes() {
return BINDABLE_INTEGER_TYPES;
public static boolean isBindableIntegerType(Class<?> theClass) {
return Integer.class.isAssignableFrom(theClass)
|| IPrimitiveType.class.isAssignableFrom(theClass);
}
public static int nonEscapedIndexOf(String theString, char theCharacter) {
@ -422,6 +411,10 @@ public class ParameterUtil {
if (theArgument instanceof Integer) {
return new IntegerDt((Integer) theArgument);
}
if (theArgument instanceof IPrimitiveType) {
IPrimitiveType<?> pt = (IPrimitiveType<?>)theArgument;
return new IntegerDt(pt.getValueAsString());
}
return null;
}

View File

@ -31,6 +31,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.ParameterUtil;
@ -52,12 +53,12 @@ public class CountParameter implements IParameter {
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
if (theOuterCollectionType != null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Since.class.getName()
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Count.class.getName()
+ " but can not be of collection type");
}
if (!ParameterUtil.getBindableIntegerTypes().contains(theParameterType)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Since.class.getName()
+ " but type '" + theParameterType + "' is an invalid type, must be one of: " + ParameterUtil.getBindableIntegerTypes());
if (!ParameterUtil.isBindableIntegerType(theParameterType)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Count.class.getName()
+ " but type '" + theParameterType + "' is an invalid type, must be Integer or IntegerType");
}
}

View File

@ -59,8 +59,14 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@Override
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
FhirContext context = getContext();
Object arg = theArgs[myTransactionParamIndex];
if (arg instanceof IBaseBundle) {
return createTransactionInvocation((IBaseBundle) arg, context);
}
@SuppressWarnings("unchecked")
List<IBaseResource> resources = (List<IBaseResource>) theArgs[myTransactionParamIndex];
List<IBaseResource> resources = (List<IBaseResource>) arg;
return createTransactionInvocation(resources, context);
}

View File

@ -139,11 +139,6 @@
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
@ -290,6 +285,19 @@
</fileSets>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>install</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-report</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>

View File

@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.RequestDetails;
@ -60,10 +61,10 @@ public class CountParameter implements IParameter {
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
if (theOuterCollectionType != null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + Since.class.getName() + " but can not be of collection type");
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + Count.class.getName() + " but can not be of collection type");
}
if (!ParameterUtil.getBindableIntegerTypes().contains(theParameterType)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + Since.class.getName() + " but type '" + theParameterType + "' is an invalid type, must be one of: " + ParameterUtil.getBindableIntegerTypes());
if (!ParameterUtil.isBindableIntegerType(theParameterType)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + Count.class.getName() + " but type '" + theParameterType + "' is an invalid type, must be one of Integer or IntegerType");
}
myType = theParameterType;
}

View File

@ -15,19 +15,15 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.api.AddProfileTagEnum;
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.Tag;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.Extension;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.api.annotation.*;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.Profile;
import ca.uhn.fhir.model.primitive.StringDt;
@ -38,9 +34,6 @@ import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class CustomTypeTest {
private static CloseableHttpClient ourClient;

View File

@ -15,12 +15,12 @@ import org.apache.http.client.methods.*;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.r4.model.Binary;
import org.hl7.fhir.r4.model.IdType;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.IdType;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.MethodOutcome;

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.List;
@ -14,18 +14,15 @@ import org.apache.http.impl.client.HttpClientBuilder;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.hl7.fhir.r4.model.Patient;
import org.junit.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.impl.HttpBasicAuthInterceptor;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.PortUtil;
@ -36,7 +33,7 @@ public class ClientIntegrationTest {
private int myPort;
private Server myServer;
private MyPatientResourceProvider myPatientProvider;
private static FhirContext ourCtx = FhirContext.forDstu1();
private static FhirContext ourCtx = FhirContext.forR4();
@Before
public void before() {
@ -60,7 +57,7 @@ public class ClientIntegrationTest {
myServer.start();
FhirContext ctx = FhirContext.forDstu1();
FhirContext ctx = FhirContext.forR4();
HttpClientBuilder builder = HttpClientBuilder.create();
// PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
@ -74,7 +71,7 @@ public class ClientIntegrationTest {
List<Patient> actualPatients = client.searchForPatients(new StringDt("AAAABBBB"));
assertEquals(1, actualPatients.size());
assertEquals("AAAABBBB", actualPatients.get(0).getNameFirstRep().getFamilyAsSingleString());
assertEquals("AAAABBBB", actualPatients.get(0).getNameFirstRep().getFamily());
assertEquals("Basic Zm9vYmFyOmJvb2JlYXI=", myPatientProvider.getAuthorizationHeader());
}
@ -92,7 +89,7 @@ public class ClientIntegrationTest {
}
@Override
public Class<? extends IResource> getResourceType() {
public Class<Patient> getResourceType() {
return Patient.class;
}
@ -105,7 +102,7 @@ public class ClientIntegrationTest {
Patient retVal = new Patient();
retVal.setId("1");
retVal.addName().addFamily(theFooParam.getValue());
retVal.addName().setFamily(theFooParam.getValue());
return Collections.singletonList(retVal);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@ -15,9 +15,9 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.hl7.fhir.r4.model.CapabilityStatement;
import org.hl7.fhir.r4.model.Patient;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
@ -25,11 +25,11 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.TestUtil;
public class ClientServerValidationDstu1Test {
@ -45,13 +45,13 @@ public class ClientServerValidationDstu1Test {
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
myFirstResponse = true;
myCtx = FhirContext.forDstu1();
myCtx = FhirContext.forR4();
myCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
}
@Test
public void testServerReturnsAppropriateVersionDstu() throws Exception {
Conformance conf = new Conformance();
CapabilityStatement conf = new CapabilityStatement();
conf.setFhirVersion("0.0.8");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
@ -88,7 +88,7 @@ public class ClientServerValidationDstu1Test {
@Test
public void testServerReturnsWrongVersionDstu() throws Exception {
Conformance conf = new Conformance();
CapabilityStatement conf = new CapabilityStatement();
conf.setFhirVersion("0.4.0");
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
@ -105,7 +105,7 @@ public class ClientServerValidationDstu1Test {
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/1"));
fail();
} catch (FhirClientInappropriateForServerException e) {
assertThat(e.toString(), containsString("The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.4.0\" which corresponds to DSTU2, but this client is configured to use DSTU1 (via the FhirContext)"));
assertThat(e.toString(), containsString("The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.4.0\" which corresponds to DSTU2, but this client is configured to use R4 (via the FhirContext)"));
}
}

View File

@ -1,7 +1,8 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.StringReader;
import java.nio.charset.Charset;
@ -14,22 +15,17 @@ import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.core.StringContains;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.hl7.fhir.r4.model.*;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdType;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.TestUtil;
@ -41,7 +37,7 @@ public class ExceptionHandlingTest {
@BeforeClass
public static void beforeClass() {
ourCtx = FhirContext.forDstu1();
ourCtx = FhirContext.forR4();
}
@Before
@ -49,7 +45,7 @@ public class ExceptionHandlingTest {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
@ -68,7 +64,7 @@ public class ExceptionHandlingTest {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
client.read(Patient.class, new IdType("Patient/1234"));
client.read().resource(Patient.class).withId(new IdType("Patient/1234")).execute();
fail();
} catch (InternalErrorException e) {
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
@ -80,7 +76,7 @@ public class ExceptionHandlingTest {
@Test
public void testFail500WithOperationOutcomeMessage() throws Exception {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getDetails().setValue("Help I'm a bug");
oo.getIssueFirstRep().getDiagnosticsElement().setValue("Help I'm a bug");
String msg = ourCtx.newXmlParser().encodeResourceToString(oo);
String contentType = Constants.CT_FHIR_XML;
@ -93,7 +89,7 @@ public class ExceptionHandlingTest {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
client.read(Patient.class, new IdType("Patient/1234"));
client.read().resource(Patient.class).withId(new IdType("Patient/1234")).execute();
fail();
} catch (InternalErrorException e) {
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
@ -118,7 +114,7 @@ public class ExceptionHandlingTest {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
client.read(Patient.class, new IdType("Patient/1234"));
client.read().resource(Patient.class).withId(new IdType("Patient/1234")).execute();
fail();
} catch (InternalErrorException e) {
assertEquals("HTTP 500 Internal Error", e.getMessage());
@ -130,7 +126,7 @@ public class ExceptionHandlingTest {
@Test
public void testFail500WithOperationOutcomeMessageJson() throws Exception {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getDetails().setValue("Help I'm a bug");
oo.getIssueFirstRep().getDiagnosticsElement().setValue("Help I'm a bug");
String msg = ourCtx.newJsonParser().encodeResourceToString(oo);
String contentType = Constants.CT_FHIR_JSON;
@ -142,7 +138,7 @@ public class ExceptionHandlingTest {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
client.read(Patient.class, new IdType("Patient/1234"));
client.read().resource(Patient.class).withId(new IdType("Patient/1234")).execute();
fail();
} catch (InternalErrorException e) {
assertThat(e.getMessage(), StringContains.containsString("HTTP 500 Internal Error"));
@ -156,7 +152,7 @@ public class ExceptionHandlingTest {
@Test
public void testFail500WithOperationOutcomeMessageGeneric() throws Exception {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getDetails().setValue("Help I'm a bug");
oo.getIssueFirstRep().getDiagnosticsElement().setValue("Help I'm a bug");
String msg = ourCtx.newJsonParser().encodeResourceToString(oo);
String contentType = Constants.CT_FHIR_JSON;

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
@ -9,28 +9,18 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.EnumerationUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Patient;
import org.junit.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdType;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.PortUtil;
@ -112,7 +102,7 @@ public class HttpProxyTest {
IGenericClient client = ourCtx.newRestfulGenericClient(baseUri);
IdType id = new IdType("Patient", "123");
client.read(Patient.class, id);
client.read().resource(Patient.class).withId(id).execute();
assertEquals("Basic dXNlcm5hbWU6cGFzc3dvcmQ=", myAuthHeader);
@ -124,13 +114,13 @@ public class HttpProxyTest {
@BeforeClass
public static void beforeClass() throws Exception {
ourCtx = FhirContext.forDstu1();
ourCtx = FhirContext.forR4();
}
public static class PatientResourceProvider implements IResourceProvider {
@Override
public Class<? extends IResource> getResourceType() {
public Class<Patient> getResourceType() {
return Patient.class;
}

View File

@ -3,11 +3,11 @@ package ca.uhn.fhir.rest.client;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.*;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.primitive.*;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.api.MethodOutcome;
@ -29,9 +29,12 @@ public interface ITestClient extends IBasicClient {
public List<Patient> getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);
@Search(type=ExtendedPatient.class)
public List<IResource> getPatientByDobWithGenericResourceReturnType(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);
public List<IBaseResource> getPatientByDobWithGenericResourceReturnType(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);
@Search()
@Search(type=ExtendedPatient.class)
public List<IAnyResource> getPatientByDobWithGenericResourceReturnType2(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);
@Search()
public List<Patient> getPatientMultipleIdentifiers(@RequiredParam(name = "ids") TokenOrListParam theIdentifiers);
@Search(queryName="someQueryNoParams")
@ -65,7 +68,7 @@ public interface ITestClient extends IBasicClient {
Bundle getHistoryPatientInstance(@IdParam IdType theId);
@History(type=Patient.class)
Bundle getHistoryPatientInstance(@IdParam IdType theId, @Since InstantDt theSince, @Count IntegerDt theCount);
Bundle getHistoryPatientInstance(@IdParam IdType theId, @Since InstantType theSince, @Count IntegerType theCount);
@History(type=Patient.class)
Bundle getHistoryPatientInstance(@IdParam IdType theId, @Since Date theSince, @Count Integer theCount);
@ -83,7 +86,7 @@ public interface ITestClient extends IBasicClient {
MethodOutcome validatePatient(@ResourceParam Patient thePatient);
@Search(type=Patient.class)
Patient findPatientQuantity(@RequiredParam(name="quantityParam") QuantityParam theQuantityDt);
Patient findPatientQuantity(@RequiredParam(name="quantityParam") QuantityParam theQuantityType);
@Search(compartmentName="compartmentName")
public List<Patient> getPatientByCompartmentAndDob(@IdParam IdType theIdType, @RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theBirthDate);

View File

@ -23,8 +23,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
@ -92,99 +90,112 @@ public class IncludedResourceStitchingClientTest {
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createLinkedBundle()), Charset.forName("UTF-8")));
IGenericClient client = ctx.newRestfulGenericClient( "http://foo");
Bundle bundle = client.search().forResource(IncludeTest.ExtPatient.class).execute();
Bundle bundle = client.search().forResource(IncludeTest.ExtPatient.class).returnBundle(Bundle.class).execute();
assertEquals(HttpGet.class, capt.getValue().getClass());
HttpGet get = (HttpGet) capt.getValue();
assertEquals("http://foo/Patient", get.getURI().toString());
assertEquals(4, bundle.size());
assertEquals(4, bundle.getEntry().size());
ExtPatient p = (ExtPatient) bundle.getEntry().get(0).getResource();
ResourceReferenceDt ref = (ResourceReferenceDt) p.getSecondOrg();
assertEquals("Organization/o1", ref.getReference().getValue());
Reference ref = (Reference) p.getSecondOrg();
assertEquals("Organization/o1", ref.getReferenceElement().getValue());
assertNotNull(ref.getResource());
Organization o1 = (Organization) ref.getResource();
assertEquals("o2", o1.getPartOf().getReference().toUnqualifiedVersionless().getIdPart());
assertEquals("o2", o1.getPartOf().getReferenceElement().toUnqualifiedVersionless().getIdPart());
assertNotNull(o1.getPartOf().getResource());
}
private String createLinkedBundle() {
//@formatter:off
return "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title/>\n" +
" <id>6cfcd90e-877a-40c6-a11c-448006712979</id>\n" +
" <link rel=\"self\" href=\"http://localhost:49782/Patient?_query=declaredExtInclude&amp;_pretty=true\"/>\n" +
" <link rel=\"fhir-base\" href=\"http://localhost:49782\"/>\n" +
" <os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults>\n" +
" <author>\n" +
" <name>HAPI FHIR Server</name>\n" +
" </author>\n" +
" <entry>\n" +
" <title>Patient p1</title>\n" +
" <id>http://localhost:49782/Patient/p1</id>\n" +
" <published>2014-08-12T10:22:19-04:00</published>\n" +
" <link rel=\"self\" href=\"http://localhost:49782/Patient/p1\"/>\n" +
" <content type=\"text/xml\">\n" +
" <Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://foo#secondOrg\">\n" +
" <valueResource>\n" +
" <reference value=\"Organization/o1\"/>\n" +
" </valueResource>\n" +
" </extension>\n" +
" <identifier>\n" +
" <label value=\"p1\"/>\n" +
" </identifier>\n" +
" </Patient>\n" +
" </content>\n" +
" </entry>\n" +
" <entry>\n" +
" <title>Patient p2</title>\n" +
" <id>http://localhost:49782/Patient/p2</id>\n" +
" <published>2014-08-12T10:22:19-04:00</published>\n" +
" <link rel=\"self\" href=\"http://localhost:49782/Patient/p2\"/>\n" +
" <content type=\"text/xml\">\n" +
" <Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://foo#secondOrg\">\n" +
" <valueResource>\n" +
" <reference value=\"Organization/o1\"/>\n" +
" </valueResource>\n" +
" </extension>\n" +
" <identifier>\n" +
" <label value=\"p2\"/>\n" +
" </identifier>\n" +
" </Patient>\n" +
" </content>\n" +
" </entry>\n" +
" <entry>\n" +
" <title>Organization o1</title>\n" +
" <id>http://localhost:49782/Organization/o1</id>\n" +
" <published>2014-08-12T10:22:19-04:00</published>\n" +
" <link rel=\"self\" href=\"http://localhost:49782/Organization/o1\"/>\n" +
" <content type=\"text/xml\">\n" +
" <Organization xmlns=\"http://hl7.org/fhir\">\n" +
" <name value=\"o1\"/>\n" +
" <partOf>\n" +
" <reference value=\"Organization/o2\"/>\n" +
" </partOf>\n" +
" </Organization>\n" +
" </content>\n" +
" </entry>\n" +
" <entry>\n" +
" <title>Organization o2</title>\n" +
" <id>http://localhost:49782/Organization/o2</id>\n" +
" <published>2014-08-12T10:22:19-04:00</published>\n" +
" <link rel=\"self\" href=\"http://localhost:49782/Organization/o2\"/>\n" +
" <content type=\"text/xml\">\n" +
" <Organization xmlns=\"http://hl7.org/fhir\">\n" +
" <name value=\"o2\"/>\n" +
" </Organization>\n" +
" </content>\n" +
" </entry>\n" +
"</feed>";
//@formatter:on
Bundle bundle = new Bundle();
Patient p1 = new Patient();
p1.addIdentifier().setValue("p1");
bundle.addEntry().setResource(p1);
Patient p2 = new Patient();
p2.addIdentifier().setValue("p1");
bundle.addEntry().setResource(p2);
return ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle);
// //@formatter:off
// return "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
// " <title/>\n" +
// " <id>6cfcd90e-877a-40c6-a11c-448006712979</id>\n" +
// " <link rel=\"self\" href=\"http://localhost:49782/Patient?_query=declaredExtInclude&amp;_pretty=true\"/>\n" +
// " <link rel=\"fhir-base\" href=\"http://localhost:49782\"/>\n" +
// " <os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults>\n" +
// " <author>\n" +
// " <name>HAPI FHIR Server</name>\n" +
// " </author>\n" +
// " <entry>\n" +
// " <title>Patient p1</title>\n" +
// " <id>http://localhost:49782/Patient/p1</id>\n" +
// " <published>2014-08-12T10:22:19-04:00</published>\n" +
// " <link rel=\"self\" href=\"http://localhost:49782/Patient/p1\"/>\n" +
// " <content type=\"text/xml\">\n" +
// " <Patient xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://foo#secondOrg\">\n" +
// " <valueResource>\n" +
// " <reference value=\"Organization/o1\"/>\n" +
// " </valueResource>\n" +
// " </extension>\n" +
// " <identifier>\n" +
// " <label value=\"p1\"/>\n" +
// " </identifier>\n" +
// " </Patient>\n" +
// " </content>\n" +
// " </entry>\n" +
// " <entry>\n" +
// " <title>Patient p2</title>\n" +
// " <id>http://localhost:49782/Patient/p2</id>\n" +
// " <published>2014-08-12T10:22:19-04:00</published>\n" +
// " <link rel=\"self\" href=\"http://localhost:49782/Patient/p2\"/>\n" +
// " <content type=\"text/xml\">\n" +
// " <Patient xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://foo#secondOrg\">\n" +
// " <valueResource>\n" +
// " <reference value=\"Organization/o1\"/>\n" +
// " </valueResource>\n" +
// " </extension>\n" +
// " <identifier>\n" +
// " <label value=\"p2\"/>\n" +
// " </identifier>\n" +
// " </Patient>\n" +
// " </content>\n" +
// " </entry>\n" +
// " <entry>\n" +
// " <title>Organization o1</title>\n" +
// " <id>http://localhost:49782/Organization/o1</id>\n" +
// " <published>2014-08-12T10:22:19-04:00</published>\n" +
// " <link rel=\"self\" href=\"http://localhost:49782/Organization/o1\"/>\n" +
// " <content type=\"text/xml\">\n" +
// " <Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <name value=\"o1\"/>\n" +
// " <partOf>\n" +
// " <reference value=\"Organization/o2\"/>\n" +
// " </partOf>\n" +
// " </Organization>\n" +
// " </content>\n" +
// " </entry>\n" +
// " <entry>\n" +
// " <title>Organization o2</title>\n" +
// " <id>http://localhost:49782/Organization/o2</id>\n" +
// " <published>2014-08-12T10:22:19-04:00</published>\n" +
// " <link rel=\"self\" href=\"http://localhost:49782/Organization/o2\"/>\n" +
// " <content type=\"text/xml\">\n" +
// " <Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <name value=\"o2\"/>\n" +
// " </Organization>\n" +
// " </content>\n" +
// " </entry>\n" +
// "</feed>";
// //@formatter:on
}

View File

@ -404,12 +404,12 @@ public class IncludeTest {
Patient p1 = new Patient();
p1.setId("p1");
p1.addIdentifier().setValue("p1");
p1.addUndeclaredExtension(false, "http://foo", new Reference(o1));
p1.addExtension(new org.hl7.fhir.r4.model.Extension("http://foo", new Reference(o1)));
Patient p2 = new Patient();
p2.setId("p2");
p2.addIdentifier().setValue("p2");
p2.addUndeclaredExtension(false, "http://foo", new Reference(o1));
p2.addExtension(new org.hl7.fhir.r4.model.Extension( "http://foo", new Reference(o1)));
return Arrays.asList(p1, p2);
}
@ -419,13 +419,13 @@ public class IncludeTest {
ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient p = new Patient();
p.addIdentifier("Mr", "Test");
p.addIdentifier().setSystem("Mr").setValue("Test");
p.setId(theName.getValue());
if (theIncludes != null) {
for (Include next : theIncludes) {
p.addName().setFamily().setValue(next.getValue());
p.addName().setFamily(next.getValue());
}
}
retVal.add(p);
@ -434,7 +434,7 @@ public class IncludeTest {
}
@Override
public Class<? extends IResource> getResourceType() {
public Class<Patient> getResourceType() {
return Patient.class;
}