Merge branch 'master' of github.com:jamesagnew/hapi-fhir into hl7org_structs
This commit is contained in:
commit
dfbe2415d1
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
|
|
|
@ -33,6 +33,22 @@ public class ClientExamples {
|
|||
// END SNIPPET: proxy
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void createTimeouts() {
|
||||
// START SNIPPET: timeouts
|
||||
FhirContext ctx = new FhirContext();
|
||||
|
||||
// Set how long to try and establish the initial TCP connection (in ms)
|
||||
ctx.getRestfulClientFactory().setConnectTimeout(20 * 1000);
|
||||
|
||||
// Set how long to block for individual read/write operations (in ms)
|
||||
ctx.getRestfulClientFactory().setSocketTimeout(20 * 1000);
|
||||
|
||||
// Create the client
|
||||
IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
|
||||
// END SNIPPET: timeouts
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void createSecurity() {
|
||||
// START SNIPPET: security
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
@ -37,12 +37,12 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
|
|||
if (myUndeclaredExtensions == null) {
|
||||
myUndeclaredExtensions = new ArrayList<ExtensionDt>();
|
||||
}
|
||||
return Collections.unmodifiableList(myUndeclaredExtensions);
|
||||
return (myUndeclaredExtensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,7 +111,7 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
|
|||
if (myUndeclaredModifierExtensions == null) {
|
||||
myUndeclaredModifierExtensions = new ArrayList<ExtensionDt>();
|
||||
}
|
||||
return Collections.unmodifiableList(myUndeclaredModifierExtensions);
|
||||
return (myUndeclaredModifierExtensions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,4 +59,16 @@ public interface IQueryParameterType {
|
|||
*/
|
||||
public String getQueryParameterQualifier();
|
||||
|
||||
/**
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
|
||||
* instead of a normal value
|
||||
*/
|
||||
Boolean getMissing();
|
||||
|
||||
/**
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
|
||||
* instead of a normal value
|
||||
*/
|
||||
void setMissing(Boolean theMissing);
|
||||
|
||||
}
|
||||
|
|
|
@ -27,22 +27,28 @@ import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
|||
public interface ISupportsUndeclaredExtensions extends IElement {
|
||||
|
||||
/**
|
||||
* Returns a list containing all undeclared non-modifier extensions
|
||||
* Returns a list containing all undeclared non-modifier extensions. The returned list
|
||||
* is mutable, so it may be modified (e.g. to add or remove an extension).
|
||||
*/
|
||||
List<ExtensionDt> getUndeclaredExtensions();
|
||||
|
||||
/**
|
||||
* Returns a list containing all undeclared extensions (modifier and non-modifier) by extension URL
|
||||
* Returns an <b>immutable</b> list containing all undeclared extensions (modifier and non-modifier) by extension URL
|
||||
*
|
||||
* @see #getUndeclaredExtensions() To return a mutable list which may be used to remove extensions
|
||||
*/
|
||||
List<ExtensionDt> getUndeclaredExtensionsByUrl(String theUrl);
|
||||
|
||||
/**
|
||||
* Returns an <b>immutable</b> list containing all extensions (modifier and non-modifier)
|
||||
* Returns an <b>immutable</b> list containing all extensions (modifier and non-modifier).
|
||||
*
|
||||
* @see #getUndeclaredExtensions() To return a mutable list which may be used to remove extensions
|
||||
*/
|
||||
List<ExtensionDt> getAllUndeclaredExtensions();
|
||||
|
||||
/**
|
||||
* Returns a list containing all undeclared modifier extensions
|
||||
* Returns a list containing all undeclared modifier extensions. The returned list
|
||||
* is mutable, so it may be modified (e.g. to add or remove an extension).
|
||||
*/
|
||||
List<ExtensionDt> getUndeclaredModifierExtensions();
|
||||
|
||||
|
@ -65,6 +71,8 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
|||
|
||||
/**
|
||||
* Adds an extension to this object
|
||||
*
|
||||
* @see #getUndeclaredExtensions() To return a mutable list which may be used to remove extensions
|
||||
*/
|
||||
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue);
|
||||
|
||||
|
@ -72,6 +80,8 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
|||
* Adds an extension to this object. This method is intended for use when
|
||||
* an extension is being added which will contain child extensions, as opposed to
|
||||
* a datatype.
|
||||
*
|
||||
* @see #getUndeclaredExtensions() To return a mutable list which may be used to remove extensions
|
||||
*/
|
||||
ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
|
||||
public abstract class BaseCodingDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -172,4 +173,28 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
|
|||
public abstract BaseCodingDt setSystem(String theUri);
|
||||
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
public abstract class BaseIdentifierDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -112,4 +113,29 @@ public abstract class BaseIdentifierDt extends BaseIdentifiableElement implement
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
public abstract class BaseQuantityDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -208,4 +210,30 @@ public abstract class BaseQuantityDt extends BaseIdentifiableElement implements
|
|||
* </p>
|
||||
*/
|
||||
public abstract DecimalDt getValueElement();
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link QuantityParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link QuantityParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import ca.uhn.fhir.model.api.BasePrimitive;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
@DatatypeDef(name = "string")
|
||||
public class StringDt extends BasePrimitive<String> implements IQueryParameterType {
|
||||
|
@ -122,4 +123,28 @@ public class StringDt extends BasePrimitive<String> implements IQueryParameterTy
|
|||
return theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,10 +153,14 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
return invokeClient(theContext, binding, clientInvocation, null, null, theLogRequestAndResponse);
|
||||
}
|
||||
|
||||
void forceConformanceCheck() {
|
||||
myFactory.validateServerBase(myUrlBase, myClient, this);
|
||||
}
|
||||
|
||||
<T> T invokeClient(FhirContext theContext, IClientResponseHandler<T> binding, BaseHttpClientInvocation clientInvocation, EncodingEnum theEncoding, Boolean thePrettyPrint, boolean theLogRequestAndResponse) {
|
||||
|
||||
if (!myDontValidateConformance) {
|
||||
myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient);
|
||||
myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient, this);
|
||||
}
|
||||
|
||||
// TODO: handle non 2xx status codes by throwing the correct exception,
|
||||
|
@ -441,4 +445,8 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
return reader;
|
||||
}
|
||||
|
||||
public List<IClientInterceptor> getInterceptors() {
|
||||
return Collections.unmodifiableList(myInterceptors);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.client.HttpClient;
|
||||
|
@ -144,11 +145,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BaseConformance conformance() {
|
||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
throw new IllegalArgumentException("Must call conformance(" + IBaseConformance.class.getSimpleName() + ") for HL7.org structures");
|
||||
throw new IllegalArgumentException("Must call conformance(" + IBaseConformance.class.getSimpleName() + ") instead of conformance() for HL7.org structures");
|
||||
}
|
||||
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation();
|
||||
|
@ -164,6 +164,11 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceConformanceCheck() {
|
||||
super.forceConformanceCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreate create() {
|
||||
return new CreateInternal();
|
||||
|
@ -588,24 +593,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return resp;
|
||||
}
|
||||
|
||||
protected IBaseResource parseResourceBody(String theResourceBody) {
|
||||
EncodingEnum encoding = null;
|
||||
for (int i = 0; i < theResourceBody.length() && encoding == null; i++) {
|
||||
switch (theResourceBody.charAt(i)) {
|
||||
case '<':
|
||||
encoding = EncodingEnum.XML;
|
||||
break;
|
||||
case '{':
|
||||
encoding = EncodingEnum.JSON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
protected IResource parseResourceBody(String theResourceBody) {
|
||||
EncodingEnum encoding = MethodUtil.detectEncodingNoDefault(theResourceBody);
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("FHIR client can't determine resource encoding");
|
||||
}
|
||||
return encoding.newParser(myContext).parseResource(theResourceBody);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T prettyPrint() {
|
||||
|
@ -635,6 +631,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
}
|
||||
|
||||
private final class StringResponseHandler implements IClientResponseHandler<String> {
|
||||
|
||||
@Override
|
||||
public String invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||
BaseServerResponseException {
|
||||
return IOUtils.toString(theResponseReader);
|
||||
}
|
||||
}
|
||||
|
||||
private class CreateInternal extends BaseClientExecutable<ICreateTyped, MethodOutcome> implements ICreate, ICreateTyped, ICreateWithQuery, ICreateWithQueryTyped {
|
||||
|
||||
private CriterionList myCriterionList;
|
||||
|
@ -1575,6 +1580,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private Bundle myBundle;
|
||||
private List<IBaseResource> myResources;
|
||||
private IBaseBundle myBaseBundle;
|
||||
private String myRawBundle;
|
||||
private EncodingEnum myRawBundleEncoding;
|
||||
|
||||
public TransactionExecutable(Bundle theResources) {
|
||||
myBundle = theResources;
|
||||
|
@ -1588,6 +1595,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myBaseBundle = theBundle;
|
||||
}
|
||||
|
||||
public TransactionExecutable(String theBundle) {
|
||||
myRawBundle = theBundle;
|
||||
myRawBundleEncoding = MethodUtil.detectEncodingNoDefault(myRawBundle);
|
||||
if (myRawBundleEncoding == null) {
|
||||
throw new IllegalArgumentException("Can not determine encoding of raw resource body");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public T execute() {
|
||||
|
@ -1600,6 +1615,19 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
ResourceResponseHandler binding = new ResourceResponseHandler(myBaseBundle.getClass(), null);
|
||||
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBaseBundle, myContext);
|
||||
return (T) invoke(params, binding, invocation);
|
||||
} else if (myRawBundle != null) {
|
||||
StringResponseHandler binding = new StringResponseHandler();
|
||||
/*
|
||||
* If the user has explicitly requested a given encoding, we may need to reencode the raw string
|
||||
*/
|
||||
if (getParamEncoding() != null) {
|
||||
if (MethodUtil.detectEncodingNoDefault(myRawBundle) != getParamEncoding()) {
|
||||
IResource parsed = parseResourceBody(myRawBundle);
|
||||
myRawBundle = getParamEncoding().newParser(getFhirContext()).encodeResourceToString(parsed);
|
||||
}
|
||||
}
|
||||
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myRawBundle, myContext);
|
||||
return (T) invoke(params, binding, invocation);
|
||||
} else {
|
||||
BundleResponseHandler binding = new BundleResponseHandler(null);
|
||||
BaseHttpClientInvocation invocation = TransactionMethodBinding.createTransactionInvocation(myBundle, myContext);
|
||||
|
@ -1629,6 +1657,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return new TransactionExecutable<T>(theBundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITransactionTyped<String> withBundle(String theBundle) {
|
||||
Validate.notBlank(theBundle, "theBundle must not be null");
|
||||
return new TransactionExecutable<String>(theBundle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
|
||||
|
|
|
@ -34,6 +34,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInnapropriateForServerException;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
import ca.uhn.fhir.rest.gclient.IDelete;
|
||||
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
|
||||
|
@ -109,6 +111,16 @@ public interface IGenericClient extends IRestfulClient {
|
|||
@Deprecated
|
||||
MethodOutcome delete(Class<? extends IResource> theType, String theId);
|
||||
|
||||
/**
|
||||
* Force the client to fetch the server's conformance statement and validate that it is appropriate for this client.
|
||||
*
|
||||
* @throws FhirClientConnectionException
|
||||
* if the conformance statement cannot be read, or if the client
|
||||
* @throws FhirClientInnapropriateForServerException
|
||||
* If the conformance statement indicates that the server is inappropriate for this client (e.g. it implements the wrong version of FHIR)
|
||||
*/
|
||||
void forceConformanceCheck() throws FhirClientConnectionException;
|
||||
|
||||
/**
|
||||
* Fluent method for the "get tags" operation
|
||||
*/
|
||||
|
@ -123,17 +135,15 @@ public interface IGenericClient extends IRestfulClient {
|
|||
* Implementation of the "history instance" method.
|
||||
*
|
||||
* @param theType
|
||||
* The type of resource to return the history for, or
|
||||
* <code>null</code> to search for history across all resources
|
||||
* The type of resource to return the history for, or <code>null</code> to search for history across all resources
|
||||
* @param theId
|
||||
* The ID of the resource to return the history for, or <code>null</code> to search for all resource
|
||||
* instances. Note that if this param is not null, <code>theType</code> must also not be null
|
||||
* The ID of the resource to return the history for, or <code>null</code> to search for all resource instances. Note that if this param is not null, <code>theType</code> must also not
|
||||
* be null
|
||||
* @param theSince
|
||||
* If not null, request that the server only return resources updated since this time
|
||||
* @param theLimit
|
||||
* If not null, request that the server return no more than this number of resources. Note that the
|
||||
* server may return less even if more are available, but should not return more according to the FHIR
|
||||
* specification.
|
||||
* If not null, request that the server return no more than this number of resources. Note that the server may return less even if more are available, but should not return more
|
||||
* according to the FHIR specification.
|
||||
* @return A bundle containing returned resources
|
||||
* @deprecated As of 0.9, use the fluent {@link #history()} method instead
|
||||
*/
|
||||
|
@ -144,31 +154,21 @@ public interface IGenericClient extends IRestfulClient {
|
|||
* Implementation of the "history instance" method.
|
||||
*
|
||||
* @param theType
|
||||
* The type of resource to return the history for, or
|
||||
* <code>null</code> to search for history across all resources
|
||||
* The type of resource to return the history for, or <code>null</code> to search for history across all resources
|
||||
* @param theId
|
||||
* The ID of the resource to return the history for, or <code>null</code> to search for all resource
|
||||
* instances. Note that if this param is not null, <code>theType</code> must also not be null
|
||||
* The ID of the resource to return the history for, or <code>null</code> to search for all resource instances. Note that if this param is not null, <code>theType</code> must also not
|
||||
* be null
|
||||
* @param theSince
|
||||
* If not null, request that the server only return resources updated since this time
|
||||
* @param theLimit
|
||||
* If not null, request that the server return no more than this number of resources. Note that the
|
||||
* server may return less even if more are available, but should not return more according to the FHIR
|
||||
* specification.
|
||||
* If not null, request that the server return no more than this number of resources. Note that the server may return less even if more are available, but should not return more
|
||||
* according to the FHIR specification.
|
||||
* @return A bundle containing returned resources
|
||||
* @deprecated As of 0.9, use the fluent {@link #history()} method instead
|
||||
*/
|
||||
@Deprecated
|
||||
<T extends IResource> Bundle history(Class<T> theType, String theId, DateTimeDt theSince, Integer theLimit);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
// /**
|
||||
// * Implementation of the "instance read" method. This method will only ever do a "read" for the latest version of a
|
||||
// * given resource instance, even if the ID passed in contains a version. If you wish to request a specific version
|
||||
|
@ -187,6 +187,13 @@ public interface IGenericClient extends IRestfulClient {
|
|||
// */
|
||||
// <T extends IBaseResource> T read(Class<T> theType, IdDt theId);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Implementation of the FHIR "extended operations" action
|
||||
*/
|
||||
|
@ -229,8 +236,7 @@ public interface IGenericClient extends IRestfulClient {
|
|||
IBaseResource read(UriDt theUrl);
|
||||
|
||||
/**
|
||||
* Register a new interceptor for this client. An interceptor can be used to add additional logging, or add security
|
||||
* headers, or pre-process responses, etc.
|
||||
* Register a new interceptor for this client. An interceptor can be used to add additional logging, or add security headers, or pre-process responses, etc.
|
||||
*/
|
||||
void registerInterceptor(IClientInterceptor theInterceptor);
|
||||
|
||||
|
@ -259,8 +265,8 @@ public interface IGenericClient extends IRestfulClient {
|
|||
Bundle search(UriDt theUrl);
|
||||
|
||||
/**
|
||||
* If set to <code>true</code>, the client will log all requests and all responses. This is probably not a good
|
||||
* production setting since it will result in a lot of extra logging, but it can be useful for troubleshooting.
|
||||
* If set to <code>true</code>, the client will log all requests and all responses. This is probably not a good production setting since it will result in a lot of extra logging, but it can be
|
||||
* useful for troubleshooting.
|
||||
*
|
||||
* @param theLogRequestAndResponse
|
||||
* Should requests and responses be logged
|
||||
|
@ -277,8 +283,7 @@ public interface IGenericClient extends IRestfulClient {
|
|||
*
|
||||
* @param theResources
|
||||
* The resources to create/update in a single transaction
|
||||
* @return A list of resource stubs (<b>these will not be fully populated</b>) containing IDs and other
|
||||
* {@link IResource#getResourceMetadata() metadata}
|
||||
* @return A list of resource stubs (<b>these will not be fully populated</b>) containing IDs and other {@link IResource#getResourceMetadata() metadata}
|
||||
* @deprecated Use {@link #transaction()}
|
||||
*
|
||||
*/
|
||||
|
@ -286,8 +291,7 @@ public interface IGenericClient extends IRestfulClient {
|
|||
List<IBaseResource> transaction(List<IBaseResource> theResources);
|
||||
|
||||
/**
|
||||
* Remove an intercaptor that was previously registered using
|
||||
* {@link IRestfulClient#registerInterceptor(IClientInterceptor)}
|
||||
* Remove an intercaptor that was previously registered using {@link IRestfulClient#registerInterceptor(IClientInterceptor)}
|
||||
*/
|
||||
void unregisterInterceptor(IClientInterceptor theInterceptor);
|
||||
|
||||
|
@ -328,18 +332,16 @@ public interface IGenericClient extends IRestfulClient {
|
|||
MethodOutcome validate(IResource theResource);
|
||||
|
||||
/**
|
||||
* Implementation of the "instance vread" method. Note that this method expects <code>theId</code> to contain a
|
||||
* resource ID as well as a version ID, and will fail if it does not.
|
||||
* Implementation of the "instance vread" method. Note that this method expects <code>theId</code> to contain a resource ID as well as a version ID, and will fail if it does not.
|
||||
* <p>
|
||||
* Note that if an absolute resource ID is passed in (i.e. a URL containing a protocol and host as well as the
|
||||
* resource type and ID) the server base for the client will be ignored, and the URL passed in will be queried.
|
||||
* Note that if an absolute resource ID is passed in (i.e. a URL containing a protocol and host as well as the resource type and ID) the server base for the client will be ignored, and the URL
|
||||
* passed in will be queried.
|
||||
* </p>
|
||||
*
|
||||
* @param theType
|
||||
* The type of resource to load
|
||||
* @param theId
|
||||
* The ID to load, including the resource ID and the resource version ID. Valid values include
|
||||
* "Patient/123/_history/222", or "http://example.com/fhir/Patient/123/_history/222"
|
||||
* The ID to load, including the resource ID and the resource version ID. Valid values include "Patient/123/_history/222", or "http://example.com/fhir/Patient/123/_history/222"
|
||||
* @return The resource
|
||||
*/
|
||||
<T extends IBaseResource> T vread(Class<T> theType, IdDt theId);
|
||||
|
|
|
@ -72,6 +72,12 @@ public interface IRestfulClientFactory {
|
|||
*/
|
||||
HttpClient getHttpClient();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getServerValidationMode()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
ServerValidationModeEnum getServerValidationModeEnum();
|
||||
|
||||
/**
|
||||
* Gets the server validation mode for any clients created from this factory. Server
|
||||
* validation involves the client requesting the server's conformance statement
|
||||
|
@ -79,8 +85,10 @@ public interface IRestfulClientFactory {
|
|||
* <p>
|
||||
* The default value for this setting is defined by {@link #DEFAULT_SERVER_VALIDATION_MODE}
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
ServerValidationModeEnum getServerValidationModeEnum();
|
||||
ServerValidationModeEnum getServerValidationMode();
|
||||
|
||||
/**
|
||||
* Gets the socket timeout, in milliseconds. This is the SO_TIMEOUT time, which is the amount of time that a
|
||||
|
@ -158,6 +166,12 @@ public interface IRestfulClientFactory {
|
|||
*/
|
||||
void setProxyCredentials(String theUsername, String thePassword);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setServerValidationMode(ServerValidationModeEnum)} instead. This method was incorrectly named.
|
||||
*/
|
||||
@Deprecated
|
||||
void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode);
|
||||
|
||||
/**
|
||||
* Sets the server validation mode for any clients created from this factory. Server
|
||||
* validation involves the client requesting the server's conformance statement
|
||||
|
@ -165,8 +179,10 @@ public interface IRestfulClientFactory {
|
|||
* <p>
|
||||
* The default value for this setting is defined by {@link #DEFAULT_SERVER_VALIDATION_MODE}
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode);
|
||||
void setServerValidationMode(ServerValidationModeEnum theServerValidationMode);
|
||||
|
||||
/**
|
||||
* Sets the socket timeout, in milliseconds. This is the SO_TIMEOUT time, which is the amount of time that a
|
||||
|
|
|
@ -51,6 +51,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInnapropriateForServerException;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
@ -137,7 +138,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ServerValidationModeEnum getServerValidationModeEnum() {
|
||||
public ServerValidationModeEnum getServerValidationMode() {
|
||||
return myServerValidationMode;
|
||||
}
|
||||
|
||||
|
@ -195,25 +196,29 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
/**
|
||||
* This method is internal to HAPI - It may change in future versions, use with caution.
|
||||
*/
|
||||
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, HttpClient theHttpClient) {
|
||||
String serverBase = theServerBase;
|
||||
if (!serverBase.endsWith("/")) {
|
||||
serverBase = serverBase + "/";
|
||||
}
|
||||
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
String serverBase = normalizeBaseUrlForMap(theServerBase);
|
||||
|
||||
switch (myServerValidationMode) {
|
||||
case NEVER:
|
||||
break;
|
||||
case ONCE:
|
||||
if (!myValidatedServerBaseUrls.contains(serverBase)) {
|
||||
validateServerBase(serverBase, theHttpClient);
|
||||
myValidatedServerBaseUrls.add(serverBase);
|
||||
validateServerBase(serverBase, theHttpClient, theClient);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String normalizeBaseUrlForMap(String theServerBase) {
|
||||
String serverBase = theServerBase;
|
||||
if (!serverBase.endsWith("/")) {
|
||||
serverBase = serverBase + "/";
|
||||
}
|
||||
return serverBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setConnectionRequestTimeout(int theConnectionRequestTimeout) {
|
||||
myConnectionRequestTimeout = theConnectionRequestTimeout;
|
||||
|
@ -258,7 +263,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode) {
|
||||
public void setServerValidationMode(ServerValidationModeEnum theServerValidationMode) {
|
||||
Validate.notNull(theServerValidationMode, "theServerValidationMode may not be null");
|
||||
myServerValidationMode = theServerValidationMode;
|
||||
}
|
||||
|
@ -269,10 +274,12 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
myHttpClient = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void validateServerBase(String theServerBase, HttpClient theHttpClient) {
|
||||
void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
|
||||
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
|
||||
for (IClientInterceptor interceptor : theClient.getInterceptors()) {
|
||||
client.registerInterceptor(interceptor);
|
||||
}
|
||||
client.setDontValidateConformance(true);
|
||||
|
||||
IBaseResource conformance;
|
||||
|
@ -296,7 +303,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
} else {
|
||||
if (serverFhirVersionString.startsWith("0.80") || serverFhirVersionString.startsWith("0.0.8")) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU1;
|
||||
} else if (serverFhirVersionString.startsWith("0.4") || serverFhirVersionString.startsWith("0.5")) {
|
||||
} else if (serverFhirVersionString.startsWith("0.4")) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
|
||||
} else if (serverFhirVersionString.startsWith("0.5")) {
|
||||
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
|
||||
|
@ -309,9 +316,22 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
if (serverFhirVersionEnum != null) {
|
||||
FhirVersionEnum contextFhirVersion = myContext.getVersion().getVersion();
|
||||
if (!contextFhirVersion.isEquivalentTo(serverFhirVersionEnum)) {
|
||||
throw new FhirClientConnectionException(myContext.getLocalizer().getMessage(RestfulClientFactory.class, "wrongVersionInConformance", theServerBase + Constants.URL_TOKEN_METADATA, serverFhirVersionString, serverFhirVersionEnum, contextFhirVersion));
|
||||
}
|
||||
throw new FhirClientInnapropriateForServerException(myContext.getLocalizer().getMessage(RestfulClientFactory.class, "wrongVersionInConformance", theServerBase + Constants.URL_TOKEN_METADATA, serverFhirVersionString, serverFhirVersionEnum, contextFhirVersion));
|
||||
}
|
||||
}
|
||||
|
||||
myValidatedServerBaseUrls.add(normalizeBaseUrlForMap(theServerBase));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerValidationModeEnum getServerValidationModeEnum() {
|
||||
return getServerValidationMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode) {
|
||||
setServerValidationMode(theServerValidationMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package ca.uhn.fhir.rest.client.exceptions;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
|
||||
/**
|
||||
* This exception will be thrown by FHIR clients if the client attempts to
|
||||
* communicate with a server which is a valid FHIR server but is incompatible
|
||||
* with this client for some reason.
|
||||
*/
|
||||
public class FhirClientInnapropriateForServerException extends BaseServerResponseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FhirClientInnapropriateForServerException(Throwable theCause) {
|
||||
super(0, theCause);
|
||||
}
|
||||
|
||||
public FhirClientInnapropriateForServerException(String theMessage, Throwable theCause) {
|
||||
super(0, theMessage, theCause);
|
||||
}
|
||||
|
||||
public FhirClientInnapropriateForServerException(String theMessage) {
|
||||
super(0, theMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
abstract class BaseClientParam implements IParam {
|
||||
|
||||
@Override
|
||||
public ICriterion<?> isMissing(boolean theMissing) {
|
||||
return new MissingCriterion(theMissing ? Constants.PARAMQUALIFIER_MISSING_TRUE : Constants.PARAMQUALIFIER_MISSING_FALSE);
|
||||
}
|
||||
|
||||
private class MissingCriterion implements ICriterion<IParam>, ICriterionInternal
|
||||
{
|
||||
private String myParameterValue;
|
||||
|
||||
|
||||
public MissingCriterion(String theParameterValue) {
|
||||
myParameterValue = theParameterValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterValue() {
|
||||
return myParameterValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterName() {
|
||||
return BaseClientParam.this.getParamName() + Constants.PARAMQUALIFIER_MISSING;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.rest.gclient;
|
|||
/**
|
||||
* Composite parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class CompositeClientParam<A extends IParam, B extends IParam> implements IParam {
|
||||
public class CompositeClientParam<A extends IParam, B extends IParam> extends BaseClientParam implements IParam {
|
||||
|
||||
private String myName;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
|
|||
/**
|
||||
* Date parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class DateClientParam implements IParam {
|
||||
public class DateClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -22,6 +22,16 @@ package ca.uhn.fhir.rest.gclient;
|
|||
|
||||
public interface IParam {
|
||||
|
||||
/**
|
||||
* Returns the name of this parameter
|
||||
*/
|
||||
String getParamName();
|
||||
|
||||
/**
|
||||
* Sets the <code>:missing</code> qualifier for this parameter. Set this to <code>true</code>
|
||||
* to indicate that the server should return resources with this value <p>populated</p>. Set this to
|
||||
* <code>false</code> to indicate that the server should return resources with this value <b>missing</b>.
|
||||
*/
|
||||
ICriterion<?> isMissing(boolean theMissing);
|
||||
|
||||
}
|
||||
|
|
|
@ -44,9 +44,9 @@ public interface ITransaction {
|
|||
*/
|
||||
<T extends IBaseBundle> ITransactionTyped<T> withBundle(T theBundleResource);
|
||||
|
||||
// *****
|
||||
// TODO: add withString version
|
||||
// If we add a withString version, make sure to auto-detect content type!
|
||||
// *****
|
||||
/**
|
||||
* Use the given raw text (should be a Bundle resource) as the transaction input
|
||||
*/
|
||||
ITransactionTyped<String> withBundle(String theBundle);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.rest.gclient;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class NumberClientParam implements IParam {
|
||||
public class NumberClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import ca.uhn.fhir.rest.gclient.NumberClientParam.IMatches;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class QuantityClientParam implements IParam {
|
||||
public class QuantityClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
*/
|
||||
|
||||
|
||||
public class ReferenceClientParam implements IParam {
|
||||
public class ReferenceClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myName;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
* @author james
|
||||
*
|
||||
*/
|
||||
public class StringClientParam implements IParam {
|
||||
public class StringClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private final String myParamName;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class TokenClientParam implements IParam {
|
||||
public class TokenClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class UriClientParam implements IParam {
|
||||
public class UriClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
//TODO: handle :above and :below
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hl7.fhir.instance.model.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
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.TagList;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
|
@ -47,6 +48,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
@ -270,7 +272,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
} else if (myContents != null) {
|
||||
contents = myContents;
|
||||
if (myContentsIsBundle) {
|
||||
if (myContentsIsBundle && myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
contentType = encoding.getBundleContentType();
|
||||
} else {
|
||||
contentType = encoding.getResourceContentType();
|
||||
|
|
|
@ -173,6 +173,25 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
*/
|
||||
public abstract String getResourceName();
|
||||
|
||||
/**
|
||||
* Returns the value of {@link #getResourceOperationType()} or {@link #getSystemOperationType()} or {@link #getOtherOperationType()}
|
||||
*/
|
||||
public String getResourceOrSystemOperationType() {
|
||||
Enum<?> retVal = getResourceOperationType();
|
||||
if (retVal != null) {
|
||||
return retVal.name();
|
||||
}
|
||||
retVal = getSystemOperationType();
|
||||
if (retVal != null) {
|
||||
return retVal.name();
|
||||
}
|
||||
retVal = getOtherOperationType();
|
||||
if (retVal != null) {
|
||||
return retVal.name();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract RestfulOperationTypeEnum getResourceOperationType();
|
||||
|
||||
public abstract RestfulOperationSystemEnum getSystemOperationType();
|
||||
|
|
|
@ -20,9 +20,12 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Enumeration;
|
||||
|
@ -32,6 +35,7 @@ import java.util.Set;
|
|||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
|
@ -53,6 +57,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||
|
@ -65,7 +70,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
|
||||
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
|
||||
if (!allowVoidReturnType()) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName() + " method but it does not return " + MethodOutcome.class);
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName()
|
||||
+ " method but it does not return " + MethodOutcome.class);
|
||||
} else if (theMethod.getReturnType() == void.class) {
|
||||
myReturnVoid = true;
|
||||
}
|
||||
|
@ -101,8 +107,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
protected abstract BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource resource);
|
||||
|
||||
/**
|
||||
* For servers, this method will match only incoming requests that match the given operation, or which have no
|
||||
* operation in the URL if this method returns null.
|
||||
* For servers, this method will match only incoming requests that match the given operation, or which have no operation in the URL if this method returns null.
|
||||
*/
|
||||
protected abstract String getMatchingOperation();
|
||||
|
||||
|
@ -126,7 +131,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
|
||||
@Override
|
||||
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||
BaseServerResponseException {
|
||||
switch (theResponseStatusCode) {
|
||||
case Constants.STATUS_HTTP_200_OK:
|
||||
case Constants.STATUS_HTTP_201_CREATED:
|
||||
|
@ -198,7 +204,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
switch (getResourceOperationType()) {
|
||||
case CREATE:
|
||||
if (response == null) {
|
||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null, which is not allowed for create operation");
|
||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName()
|
||||
+ " returned null, which is not allowed for create operation");
|
||||
}
|
||||
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
|
@ -271,10 +278,40 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
/**
|
||||
* @throws IOException
|
||||
*/
|
||||
protected IBaseResource parseIncomingServerResource(Request theRequest) throws IOException {
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncoding(theRequest);
|
||||
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
|
||||
|
||||
Reader requestReader;
|
||||
EncodingEnum encoding = RestfulServerUtils.determineRequestEncodingNoDefault(theRequest);
|
||||
if (encoding == null) {
|
||||
String ctValue = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
if (ctValue != null) {
|
||||
if (ctValue.startsWith("application/x-www-form-urlencoded")) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "invalidContentTypeInRequest", ctValue, getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
if (isBlank(ctValue)) {
|
||||
/*
|
||||
* If the client didn't send a content type, try to guess
|
||||
*/
|
||||
requestReader = theRequest.getServletRequest().getReader();
|
||||
String body = IOUtils.toString(requestReader);
|
||||
encoding = MethodUtil.detectEncodingNoDefault(body);
|
||||
if (encoding == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "noContentTypeInRequest", getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
} else {
|
||||
requestReader = new StringReader(body);
|
||||
}
|
||||
} else {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBinding.class, "invalidContentTypeInRequest", ctValue, getResourceOrSystemOperationType());
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
} else {
|
||||
requestReader = theRequest.getServletRequest().getReader();
|
||||
}
|
||||
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
BufferedReader requestReader = theRequest.getServletRequest().getReader();
|
||||
|
||||
Class<? extends IBaseResource> wantedResourceType = requestContainsResourceType();
|
||||
IBaseResource retVal;
|
||||
|
@ -305,7 +342,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
return null;
|
||||
}
|
||||
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, Request theRequest) throws IOException {
|
||||
protected void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, Request theRequest)
|
||||
throws IOException {
|
||||
theResponse.setStatus(theE.getStatusCode());
|
||||
|
||||
theServer.addHeadersToResponse(theResponse);
|
||||
|
|
|
@ -249,15 +249,26 @@ public class MethodUtil {
|
|||
}
|
||||
|
||||
public static EncodingEnum detectEncoding(String theBody) {
|
||||
for (int i = 0; i < theBody.length(); i++) {
|
||||
EncodingEnum retVal = detectEncodingNoDefault(theBody);
|
||||
if (retVal == null) {
|
||||
retVal = EncodingEnum.XML;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static EncodingEnum detectEncodingNoDefault(String theBody) {
|
||||
EncodingEnum retVal = null;
|
||||
for (int i = 0; i < theBody.length() && retVal == null; i++) {
|
||||
switch (theBody.charAt(i)) {
|
||||
case '<':
|
||||
return EncodingEnum.XML;
|
||||
retVal = EncodingEnum.XML;
|
||||
break;
|
||||
case '{':
|
||||
return EncodingEnum.JSON;
|
||||
retVal = EncodingEnum.JSON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
|
|
|
@ -199,4 +199,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
return new HttpPostClientInvocation(theContext, theResources, BundleTypeEnum.TRANSACTION);
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createTransactionInvocation(String theRawBundle, FhirContext theContext) {
|
||||
return new HttpPostClientInvocation(theContext, theRawBundle, true, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,54 +26,76 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
/**
|
||||
* Base class for RESTful operation parameter types
|
||||
*/
|
||||
public class BaseParam implements IQueryParameterType {
|
||||
abstract class BaseParam implements IQueryParameterType {
|
||||
|
||||
private Boolean myMissing;
|
||||
|
||||
/**
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
|
||||
* instead of a normal value
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale instead of a normal value
|
||||
*/
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myMissing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
public final String getQueryParameterQualifier() {
|
||||
if (myMissing != null) {
|
||||
return Constants.PARAMQUALIFIER_MISSING;
|
||||
}
|
||||
return null;
|
||||
return doGetQueryParameterQualifier();
|
||||
}
|
||||
|
||||
abstract String doGetQueryParameterQualifier();
|
||||
|
||||
abstract String doGetValueAsQueryToken();
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
public final String getValueAsQueryToken() {
|
||||
if (myMissing != null) {
|
||||
return myMissing ? "true" : "false";
|
||||
return myMissing ? Constants.PARAMQUALIFIER_MISSING_TRUE : Constants.PARAMQUALIFIER_MISSING_FALSE;
|
||||
}
|
||||
return null;
|
||||
return doGetValueAsQueryToken();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
|
||||
* instead of a normal value
|
||||
* If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale instead of a normal value
|
||||
*/
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myMissing = theMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
public final void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_MISSING.equals(theQualifier)) {
|
||||
myMissing = "true".equals(theValue);
|
||||
doSetValueAsQueryToken(null, null);
|
||||
} else {
|
||||
myMissing = null;
|
||||
doSetValueAsQueryToken(theQualifier, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void doSetValueAsQueryToken(String theQualifier, String theValue);
|
||||
|
||||
static class ComposableBaseParam extends BaseParam{
|
||||
|
||||
@Override
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> implements IQueryParameterType {
|
||||
public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> extends BaseParam implements IQueryParameterType {
|
||||
|
||||
private A myLeftType;
|
||||
private B myRightType;
|
||||
|
@ -59,27 +59,13 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the left value for this parameter (the first of two parameters in this composite)
|
||||
*/
|
||||
public A getLeftValue() {
|
||||
return myLeftType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the right value for this parameter (the second of two parameters in this composite)
|
||||
*/
|
||||
public B getRightValue() {
|
||||
return myRightType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
String doGetValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (myLeftType != null) {
|
||||
b.append(myLeftType.getValueAsQueryToken());
|
||||
|
@ -92,7 +78,7 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (isBlank(theValue)) {
|
||||
myLeftType.setValueAsQueryToken(theQualifier, "");
|
||||
myRightType.setValueAsQueryToken(theQualifier, "");
|
||||
|
@ -108,4 +94,18 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the left value for this parameter (the first of two parameters in this composite)
|
||||
*/
|
||||
public A getLeftValue() {
|
||||
return myLeftType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the right value for this parameter (the second of two parameters in this composite)
|
||||
*/
|
||||
public B getRightValue() {
|
||||
return myRightType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
public class DateParam extends DateTimeDt implements IQueryParameterType, IQueryParameterOr<DateParam> {
|
||||
|
||||
private QuantityCompararatorEnum myComparator;
|
||||
private BaseParam myBase=new BaseParam();
|
||||
private BaseParam myBase=new BaseParam.ComposableBaseParam();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -191,4 +191,14 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
|
|||
return new DateTimeDt(getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myBase.getMissing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myBase.setMissing(theMissing);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -365,6 +365,16 @@ public class InternalCodingDt extends BaseCodingDt implements ICompositeDatatype
|
|||
return getDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -414,6 +414,16 @@ class InternalQuantityDt
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -45,32 +45,24 @@ public class NumberParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(getClass().getSimpleName());
|
||||
b.append("[");
|
||||
if (myQuantity.getComparatorElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getComparatorElement().getValue());
|
||||
}
|
||||
if (myQuantity.getValueElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getValueElement().toString());
|
||||
}
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return myQuantity.getValueElement().getValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (getMissing() != null && isBlank(theValue)) {
|
||||
return;
|
||||
}
|
||||
|
@ -92,25 +84,28 @@ public class NumberParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return myQuantity.getValueElement().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(getClass().getSimpleName());
|
||||
b.append("[");
|
||||
if (myQuantity.getComparatorElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getComparatorElement().getValue());
|
||||
}
|
||||
if (myQuantity.getValueElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getValueElement().toString());
|
||||
}
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
return super.getQueryParameterQualifier();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -142,33 +142,13 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
myApproximate = false;
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
@Override
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
return super.getQueryParameterQualifier();
|
||||
}
|
||||
|
||||
public UriDt getSystem() {
|
||||
return myQuantity.getSystemElement();
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return myQuantity.getUnitsElement().getValue();
|
||||
}
|
||||
|
||||
public DecimalDt getValue() {
|
||||
return myQuantity.getValueElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
if (super.getMissing() != null) {
|
||||
return super.getValueAsQueryToken();
|
||||
}
|
||||
|
||||
String doGetValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (myApproximate) {
|
||||
b.append('~');
|
||||
|
@ -191,6 +171,62 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
clear();
|
||||
|
||||
if (theValue == null) {
|
||||
return;
|
||||
}
|
||||
List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
|
||||
|
||||
if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
|
||||
if (parts.get(0).startsWith("~")) {
|
||||
myQuantity.setComparator((QuantityCompararatorEnum) null);
|
||||
myApproximate = true;
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else if (parts.get(0).startsWith("<=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith("<")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN);
|
||||
String valStr = parts.get(0).substring(1);
|
||||
myQuantity.setValue(new BigDecimal(valStr));
|
||||
} else if (parts.get(0).startsWith(">=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith(">")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else {
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0)));
|
||||
}
|
||||
}
|
||||
if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
|
||||
myQuantity.setSystem(parts.get(1));
|
||||
}
|
||||
if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
|
||||
myQuantity.setUnits(parts.get(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public UriDt getSystem() {
|
||||
return myQuantity.getSystemElement();
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return myQuantity.getUnitsElement().getValue();
|
||||
}
|
||||
|
||||
public DecimalDt getValue() {
|
||||
return myQuantity.getValueElement();
|
||||
}
|
||||
|
||||
public boolean isApproximate() {
|
||||
return myApproximate;
|
||||
}
|
||||
|
@ -253,51 +289,6 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
clear();
|
||||
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
if (getMissing() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (theValue == null) {
|
||||
return;
|
||||
}
|
||||
List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
|
||||
|
||||
if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
|
||||
if (parts.get(0).startsWith("~")) {
|
||||
myQuantity.setComparator((QuantityCompararatorEnum) null);
|
||||
myApproximate = true;
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else if (parts.get(0).startsWith("<=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith("<")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN);
|
||||
String valStr = parts.get(0).substring(1);
|
||||
myQuantity.setValue(new BigDecimal(valStr));
|
||||
} else if (parts.get(0).startsWith(">=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith(">")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else {
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0)));
|
||||
}
|
||||
}
|
||||
if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
|
||||
myQuantity.setSystem(parts.get(1));
|
||||
}
|
||||
if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
|
||||
myQuantity.setUnits(parts.get(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
|
|
@ -32,7 +32,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
public class ReferenceParam extends IdDt implements IQueryParameterType {
|
||||
|
||||
private String myChain;
|
||||
private BaseParam myBase=new BaseParam();
|
||||
private BaseParam myBase=new BaseParam.ComposableBaseParam();
|
||||
|
||||
public ReferenceParam() {
|
||||
}
|
||||
|
@ -206,4 +206,14 @@ public class ReferenceParam extends IdDt implements IQueryParameterType {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myBase.getMissing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myBase.setMissing(theMissing);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,23 +48,35 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
}else if (isExact()) {
|
||||
String doGetQueryParameterQualifier() {
|
||||
if (isExact()) {
|
||||
return Constants.PARAMQUALIFIER_STRING_EXACT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
setExact(true);
|
||||
} else {
|
||||
setExact(false);
|
||||
}
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -87,16 +99,6 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
setExact(true);
|
||||
} else {
|
||||
setExact(false);
|
||||
}
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -104,11 +106,10 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
if (myExact) {
|
||||
builder.append("exact", myExact);
|
||||
}
|
||||
if (getMissing() != null) {
|
||||
builder.append("missing", getMissing().booleanValue());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,21 +41,6 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
public TokenParam() {
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue) {
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue, boolean theText) {
|
||||
if (theText && isNotBlank(theSystem)) {
|
||||
throw new IllegalArgumentException(
|
||||
"theSystem can not be non-blank if theText is true (:text searches do not include a system). In other words, set the first parameter to null for a text search");
|
||||
}
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
setText(theText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which copies the {@link InternalCodingDt#getSystemElement() system} and {@link InternalCodingDt#getCodeElement() code} from a {@link InternalCodingDt} instance and adds it as a parameter
|
||||
*
|
||||
|
@ -76,21 +61,56 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
this(toSystemValue(theIdentifierDt.getSystemElement()), theIdentifierDt.getValueElement().getValue());
|
||||
}
|
||||
|
||||
private static String toSystemValue(UriDt theSystem) {
|
||||
return theSystem.getValueAsString();
|
||||
public TokenParam(String theSystem, String theValue) {
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue, boolean theText) {
|
||||
if (theText && isNotBlank(theSystem)) {
|
||||
throw new IllegalArgumentException(
|
||||
"theSystem can not be non-blank if theText is true (:text searches do not include a system). In other words, set the first parameter to null for a text search");
|
||||
}
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
setText(theText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
} else if (isText()) {
|
||||
String doGetQueryParameterQualifier() {
|
||||
if (isText()) {
|
||||
return Constants.PARAMQUALIFIER_TOKEN_TEXT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
if (getSystem() != null) {
|
||||
return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
|
||||
} else {
|
||||
return ParameterUtil.escape(getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theParameter) {
|
||||
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(theParameter.substring(0, barIndex));
|
||||
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
|
||||
} else {
|
||||
setValue(ParameterUtil.unescape(theParameter));
|
||||
}
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
@ -99,18 +119,8 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
return myValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
if (getMissing() != null) {
|
||||
return super.getValueAsQueryToken();
|
||||
} else if (getSystem() != null) {
|
||||
return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
|
||||
} else {
|
||||
return ParameterUtil.escape(getValue());
|
||||
}
|
||||
public InternalCodingDt getValueAsCoding() {
|
||||
return new InternalCodingDt(mySystem, myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -137,25 +147,6 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theParameter) {
|
||||
super.setValueAsQueryToken(theQualifier, theParameter);
|
||||
if (getMissing() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(theParameter.substring(0, barIndex));
|
||||
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
|
||||
} else {
|
||||
setValue(ParameterUtil.unescape(theParameter));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -170,8 +161,8 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public InternalCodingDt getValueAsCoding() {
|
||||
return new InternalCodingDt(mySystem, myValue);
|
||||
private static String toSystemValue(UriDt theSystem) {
|
||||
return theSystem.getValueAsString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,21 +42,30 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
} else {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public UriDt getValueAsUriDt() {
|
||||
return new UriDt(myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -71,11 +80,6 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -83,12 +87,4 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public UriDt getValueAsUriDt() {
|
||||
return new UriDt(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_304_NOT_MODIFIED = 304;
|
||||
public static final int STATUS_HTTP_400_BAD_REQUEST = 400;
|
||||
public static final int STATUS_HTTP_401_CLIENT_UNAUTHORIZED = 401;
|
||||
public static final int STATUS_HTTP_403_FORBIDDEN= 403;
|
||||
public static final int STATUS_HTTP_404_NOT_FOUND = 404;
|
||||
public static final int STATUS_HTTP_405_METHOD_NOT_ALLOWED = 405;
|
||||
public static final int STATUS_HTTP_409_CONFLICT = 409;
|
||||
|
@ -124,6 +125,8 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -205,9 +205,18 @@ public class RestfulServerUtils {
|
|||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncoding(Request theReq) {
|
||||
EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static EncodingEnum determineRequestEncodingNoDefault(Request theReq) {
|
||||
EncodingEnum retVal = null;
|
||||
Enumeration<String> acceptValues = theReq.getServletRequest().getHeaders(Constants.HEADER_CONTENT_TYPE);
|
||||
if (acceptValues != null) {
|
||||
while (acceptValues.hasMoreElements()) {
|
||||
while (acceptValues.hasMoreElements() && retVal == null) {
|
||||
String nextAcceptHeaderValue = acceptValues.nextElement();
|
||||
if (nextAcceptHeaderValue != null && isNotBlank(nextAcceptHeaderValue)) {
|
||||
for (String nextPart : nextAcceptHeaderValue.split(",")) {
|
||||
|
@ -219,16 +228,16 @@ public class RestfulServerUtils {
|
|||
nextPart = nextPart.substring(0, scIdx);
|
||||
}
|
||||
nextPart = nextPart.trim();
|
||||
EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
|
||||
try {
|
||||
|
|
|
@ -50,6 +50,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
registerExceptionType(PreconditionFailedException.STATUS_CODE, PreconditionFailedException.class);
|
||||
registerExceptionType(ResourceVersionConflictException.STATUS_CODE, ResourceVersionConflictException.class);
|
||||
registerExceptionType(UnprocessableEntityException.STATUS_CODE, UnprocessableEntityException.class);
|
||||
registerExceptionType(ForbiddenOperationException.STATUS_CODE, ForbiddenOperationException.class);
|
||||
}
|
||||
|
||||
private List<String> myAdditionalMessages = null;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* This Represents an <b>HTTP 403 Forbidden</b> response, which generally indicates one of two conditions:
|
||||
* <ul>
|
||||
* <li>Authentication was provided, but the authenticated user is not permitted to perform the requested operation.</li>
|
||||
* <li>The operation is forbidden to all users. Repeating the request with authentication would serve no purpose.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Note that a complete list of RESTful exceptions is available in the <a href="./package-summary.html">Package
|
||||
* Summary</a>.
|
||||
* </p>
|
||||
*/
|
||||
public class ForbiddenOperationException extends BaseServerResponseException {
|
||||
|
||||
public static final int STATUS_CODE = Constants.STATUS_HTTP_403_FORBIDDEN;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ForbiddenOperationException(String theMessage) {
|
||||
super(STATUS_CODE, theMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theMessage
|
||||
* The message
|
||||
* @param theOperationOutcome
|
||||
* The OperationOutcome resource to return to the client
|
||||
*/
|
||||
public ForbiddenOperationException(String theMessage, BaseOperationOutcome theOperationOutcome) {
|
||||
super(STATUS_CODE, theMessage, theOperationOutcome);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package org.hl7.fhir.instance.model.api;
|
||||
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
<<<<<<< HEAD:hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/model/IBaseResource.java
|
||||
/**
|
||||
* For now, this is a simple marker interface indicating that a class is a resource type.
|
||||
* There are two concrete types of implementations of this interrface. The first are
|
||||
* HL7.org's Resource structures (e.g.
|
||||
* <code>org.hl7.fhir.instance.model.Patient</code>) and
|
||||
* the second are HAPI's Resource structures, e.g.
|
||||
* <code>ca.uhn.fhir.model.dstu.resource.Patient</code>)
|
||||
*/
|
||||
public interface IBaseResource extends IBase {
|
||||
|
||||
IIdType
|
||||
=======
|
||||
public interface IBaseEnumeration<T extends Enum<?>> extends IPrimitiveType<T> {
|
||||
|
||||
// Marker interface
|
||||
>>>>>>> 2edc7eadab64d171ddc1b7c971ff36b9eb55ce67:hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IBaseEnumeration.java
|
||||
|
||||
}
|
|
@ -12,6 +12,9 @@ ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable
|
|||
ca.uhn.fhir.rest.client.RestfulClientFactory.failedToRetrieveConformance=Failed to retrieve the server's metadata statement during client initialization. URL used was: {0}
|
||||
ca.uhn.fhir.rest.client.RestfulClientFactory.wrongVersionInConformance=The server at base URL "{0}" returned a conformance statement indicating that it supports FHIR version "{1}" which corresponds to {2}, but this client is configured to use {3} (via the FhirContext).
|
||||
|
||||
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBinding.noContentTypeInRequest=No Content-Type header was provided in the request. This is required for "{0}" operation
|
||||
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBinding.invalidContentTypeInRequest=Incorrect Content-Type header value of "{0}" was provided in the request. A FHIR Content-Type is required for "{1}" operation
|
||||
|
||||
ca.uhn.fhir.rest.method.OperationMethodBinding.methodNotSupported=HTTP Method {0} is not allowed for this operation. Allowed method(s): {1}
|
||||
ca.uhn.fhir.rest.method.OperationParamBinder.urlParamNotPrimitive=Can not invoke operation {0} using HTTP GET because parameter {1} is not a primitive datatype
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid {2} parameter value: "{0}". Valid values are: {1}
|
||||
|
@ -39,4 +42,5 @@ ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0
|
|||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
|
@ -62,7 +62,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,17 +18,17 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
|
@ -42,13 +42,13 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
@ -373,7 +373,7 @@
|
|||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build_dstu1</id>
|
||||
|
@ -404,12 +404,12 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
|
|
@ -23,8 +23,10 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -424,16 +426,14 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
// Get list of IDs
|
||||
searchHistoryCurrentVersion(theResourceName, theId, theSince, end.getValue(), limit, tuples);
|
||||
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
|
||||
ourLog.info("Retrieved {} history IDs from current versions in {} ms", tuples.size(), timer.getMillisAndRestart());
|
||||
|
||||
searchHistoryHistory(theResourceName, theId, theSince, end.getValue(), limit, tuples);
|
||||
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
|
||||
ourLog.info("Retrieved {} history IDs from previous versions in {} ms", tuples.size(), timer.getMillisAndRestart());
|
||||
|
||||
// Sort merged list
|
||||
Collections.sort(tuples, Collections.reverseOrder());
|
||||
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
|
||||
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated()) : tuples.toString();
|
||||
|
||||
return new IBundleProvider() {
|
||||
|
||||
|
@ -641,7 +641,12 @@ public abstract class BaseFhirDao implements IDao {
|
|||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
String matchUrl = theMatchUrl;
|
||||
if (matchUrl.indexOf('?') == -1) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: URL does not contain any parameters ('?' not detected)");
|
||||
}
|
||||
matchUrl = matchUrl.replace("|", "%7C");
|
||||
parameters = URLEncodedUtils.parse(new URI(matchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
@ -1045,6 +1050,9 @@ public abstract class BaseFhirDao implements IDao {
|
|||
quantityParams = extractSearchParamQuantity(entity, theResource);
|
||||
dateParams = extractSearchParamDates(entity, theResource);
|
||||
|
||||
ourLog.info("Indexing resource: {}", entity.getId());
|
||||
ourLog.info("Storing string indexes: {}", stringParams);
|
||||
|
||||
tokenParams = new ArrayList<ResourceIndexedSearchParamToken>();
|
||||
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(entity, theResource)) {
|
||||
if (next instanceof ResourceIndexedSearchParamToken) {
|
||||
|
|
|
@ -51,6 +51,7 @@ import javax.persistence.criteria.Order;
|
|||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.criteria.Subquery;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -71,6 +72,7 @@ import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
|
@ -140,6 +142,8 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
private String mySecondaryPrimaryKeyParamName;
|
||||
|
||||
private Set<Long> addPredicateComposite(RuntimeSearchParam theParamDef, Set<Long> thePids, List<? extends IQueryParameterType> theNextAnd) {
|
||||
// TODO: fail if missing is set for a composite query
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
|
@ -177,6 +181,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsDate", theParamName, ResourceIndexedSearchParamDate.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamDate> from = cq.from(ResourceIndexedSearchParamDate.class);
|
||||
|
@ -184,6 +192,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
|
||||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IQueryParameterType params = nextOr;
|
||||
Predicate p = createPredicateDate(builder, from, params);
|
||||
codePredicates.add(p);
|
||||
|
@ -204,50 +216,6 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Predicate addPredicateDateFromRange(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, DateRangeParam theRange) {
|
||||
Date lowerBound = theRange.getLowerBoundAsInstant();
|
||||
Date upperBound = theRange.getUpperBoundAsInstant();
|
||||
|
||||
Predicate lb = null;
|
||||
if (lowerBound != null) {
|
||||
Predicate gt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueLow"), lowerBound);
|
||||
Predicate lt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueHigh"), lowerBound);
|
||||
lb = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate hbo = builder.or(lt, lin);
|
||||
// lb = builder.and(lbo, hbo);
|
||||
}
|
||||
|
||||
Predicate ub = null;
|
||||
if (upperBound != null) {
|
||||
Predicate gt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueLow"), upperBound);
|
||||
Predicate lt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueHigh"), upperBound);
|
||||
ub = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate ubo = builder.or(lt, lin);
|
||||
// ub = builder.and(ubo, lbo);
|
||||
|
||||
}
|
||||
|
||||
if (lb != null && ub != null) {
|
||||
return (theBuilder.and(lb, ub));
|
||||
} else if (lb != null) {
|
||||
return (lb);
|
||||
} else {
|
||||
return (ub);
|
||||
}
|
||||
}
|
||||
|
||||
// private Set<Long> addPredicateComposite(String theParamName, Set<Long> thePids, List<? extends
|
||||
// IQueryParameterType> theList) {
|
||||
// }
|
||||
|
||||
private Set<Long> addPredicateId(Set<Long> theExistingPids, Set<Long> thePids) {
|
||||
if (thePids == null || thePids.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
|
@ -272,6 +240,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return found;
|
||||
}
|
||||
|
||||
// private Set<Long> addPredicateComposite(String theParamName, Set<Long> thePids, List<? extends
|
||||
// IQueryParameterType> theList) {
|
||||
// }
|
||||
|
||||
private Set<Long> addPredicateLanguage(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
|
@ -322,6 +294,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsNumber", theParamName, ResourceIndexedSearchParamNumber.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamNumber> from = cq.from(ResourceIndexedSearchParamNumber.class);
|
||||
|
@ -331,6 +307,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (params instanceof NumberParam) {
|
||||
NumberParam param = (NumberParam) params;
|
||||
|
||||
|
@ -384,11 +364,76 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
|
||||
String resourceType = getContext().getResourceDefinition(getResourceType()).getName();
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.select(from.get("myId").as(Long.class));
|
||||
|
||||
Subquery<Long> subQ = cq.subquery(Long.class);
|
||||
Root<? extends BaseResourceIndexedSearchParam> subQfrom = subQ.from(theParamTable);
|
||||
subQ.select(subQfrom.get("myResourcePid").as(Long.class));
|
||||
Predicate subQname = builder.equal(subQfrom.get("myParamName"), theParamName);
|
||||
Predicate subQtype = builder.equal(subQfrom.get("myResourceType"), resourceType);
|
||||
subQ.where(builder.and(subQtype, subQname));
|
||||
|
||||
Predicate joinPredicate = builder.not(builder.in(from.get("myId")).value(subQ));
|
||||
Predicate typePredicate = builder.equal(from.get("myResourceType"), resourceType);
|
||||
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myId").in(thePids));
|
||||
cq.where(builder.and(inPids, typePredicate, joinPredicate));
|
||||
} else {
|
||||
cq.where(builder.and(typePredicate, joinPredicate));
|
||||
}
|
||||
|
||||
ourLog.info("Adding :missing qualifier for parameter '{}'", theParamName);
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
List<Long> resultList = q.getResultList();
|
||||
HashSet<Long> retVal = new HashSet<Long>(resultList);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateParamMissingResourceLink(Set<Long> thePids, String joinName, String theParamName) {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.select(from.get("myId").as(Long.class));
|
||||
|
||||
Subquery<Long> subQ = cq.subquery(Long.class);
|
||||
Root<ResourceLink> subQfrom = subQ.from(ResourceLink.class);
|
||||
subQ.select(subQfrom.get("mySourceResourcePid").as(Long.class));
|
||||
|
||||
// subQ.where(builder.equal(subQfrom.get("myParamName"), theParamName));
|
||||
subQ.where(createResourceLinkPathPredicate(theParamName, builder, subQfrom));
|
||||
|
||||
Predicate joinPredicate = builder.not(builder.in(from.get("myId")).value(subQ));
|
||||
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myId").in(thePids));
|
||||
cq.where(builder.and(inPids, joinPredicate));
|
||||
} else {
|
||||
cq.where(joinPredicate);
|
||||
}
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
List<Long> resultList = q.getResultList();
|
||||
HashSet<Long> retVal = new HashSet<Long>(resultList);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsQuantity", theParamName, ResourceIndexedSearchParamQuantity.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamQuantity> from = cq.from(ResourceIndexedSearchParamQuantity.class);
|
||||
|
@ -398,6 +443,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String systemValue;
|
||||
String unitsValue;
|
||||
QuantityCompararatorEnum cmpValue;
|
||||
|
@ -499,6 +548,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return pidsToRetain;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissingResourceLink(thePids, "myResourceLinks", theParamName);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceLink> from = cq.from(ResourceLink.class);
|
||||
|
@ -509,6 +562,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresentForResourceLink(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (params instanceof ReferenceParam) {
|
||||
ReferenceParam ref = (ReferenceParam) params;
|
||||
|
||||
|
@ -573,10 +630,7 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
|
||||
Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0]));
|
||||
|
||||
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
||||
String path = param.getPath();
|
||||
|
||||
Predicate type = builder.equal(from.get("mySourcePath"), path);
|
||||
Predicate type = createResourceLinkPathPredicate(theParamName, builder, from);
|
||||
if (pidsToRetain.size() > 0) {
|
||||
Predicate inPids = (from.get("mySourceResourcePid").in(pidsToRetain));
|
||||
cq.where(builder.and(type, masterCodePredicate, inPids));
|
||||
|
@ -588,11 +642,23 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Predicate createResourceLinkPathPredicate(String theParamName, CriteriaBuilder builder, Root<? extends ResourceLink> from) {
|
||||
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
||||
String path = param.getPath();
|
||||
|
||||
Predicate type = builder.equal(from.get("mySourcePath"), path);
|
||||
return type;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateString(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsString", theParamName, ResourceIndexedSearchParamString.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamString> from = cq.from(ResourceIndexedSearchParamString.class);
|
||||
|
@ -601,6 +667,9 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType theParameter = nextOr;
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Predicate singleCode = createPredicateString(theParameter, theParamName, builder, from);
|
||||
codePredicates.add(singleCode);
|
||||
|
@ -621,11 +690,43 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||
}
|
||||
Predicate singleCode = from.get("myId").isNotNull();
|
||||
Predicate name = theBuilder.equal(from.get("myParamName"), theParamName);
|
||||
codePredicates.add(theBuilder.and(name, singleCode));
|
||||
missingFalse = true;
|
||||
}
|
||||
return missingFalse;
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||
}
|
||||
Predicate singleCode = from.get("mySourceResource").isNotNull();
|
||||
Predicate name = createResourceLinkPathPredicate(theParamName, theBuilder, from);
|
||||
codePredicates.add(theBuilder.and(name, singleCode));
|
||||
missingFalse = true;
|
||||
}
|
||||
return missingFalse;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsToken", theParamName, ResourceIndexedSearchParamToken.class);
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamToken> from = cq.from(ResourceIndexedSearchParamToken.class);
|
||||
|
@ -633,6 +734,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
|
||||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
if (addPredicateMissingFalseIfPresent(builder, theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nextOr instanceof TokenParam) {
|
||||
TokenParam id = (TokenParam) nextOr;
|
||||
if (id.isText()) {
|
||||
|
@ -758,20 +863,60 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
DateParam date = (DateParam) theParam;
|
||||
if (!date.isEmpty()) {
|
||||
DateRangeParam range = new DateRangeParam(date);
|
||||
p = addPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
p = createPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
} else {
|
||||
// TODO: handle missing date param?
|
||||
p = null;
|
||||
}
|
||||
} else if (theParam instanceof DateRangeParam) {
|
||||
DateRangeParam range = (DateRangeParam) theParam;
|
||||
p = addPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
p = createPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid token type: " + theParam.getClass());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private Predicate createPredicateDateFromRange(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, DateRangeParam theRange) {
|
||||
Date lowerBound = theRange.getLowerBoundAsInstant();
|
||||
Date upperBound = theRange.getUpperBoundAsInstant();
|
||||
|
||||
Predicate lb = null;
|
||||
if (lowerBound != null) {
|
||||
Predicate gt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueLow"), lowerBound);
|
||||
Predicate lt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueHigh"), lowerBound);
|
||||
lb = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate hbo = builder.or(lt, lin);
|
||||
// lb = builder.and(lbo, hbo);
|
||||
}
|
||||
|
||||
Predicate ub = null;
|
||||
if (upperBound != null) {
|
||||
Predicate gt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueLow"), upperBound);
|
||||
Predicate lt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueHigh"), upperBound);
|
||||
ub = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate ubo = builder.or(lt, lin);
|
||||
// ub = builder.and(ubo, lbo);
|
||||
|
||||
}
|
||||
|
||||
if (lb != null && ub != null) {
|
||||
return (theBuilder.and(lb, ub));
|
||||
} else if (lb != null) {
|
||||
return (lb);
|
||||
} else {
|
||||
return (ub);
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
|
||||
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
|
||||
String rawSearchTerm;
|
||||
|
@ -1531,9 +1676,8 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
loadResourcesByPid(pidsSubList, retVal, BundleEntrySearchModeEnum.MATCH);
|
||||
|
||||
/*
|
||||
* Load _include resources - Note that _revincludes are handled differently
|
||||
* than _include ones, as they are counted towards the total count and paged,
|
||||
* so they are loaded outside the bundle provider
|
||||
* Load _include resources - Note that _revincludes are handled differently than _include ones, as they are counted towards the total count and paged, so they are loaded
|
||||
* outside the bundle provider
|
||||
*/
|
||||
if (theParams.getIncludes() != null && theParams.getIncludes().isEmpty() == false) {
|
||||
Set<IdDt> previouslyLoadedPids = new HashSet<IdDt>();
|
||||
|
@ -1861,7 +2005,7 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
resourceId = entity.getIdDt();
|
||||
} else {
|
||||
return create(theResource);
|
||||
return create(theResource, null, thePerformIndexing);
|
||||
}
|
||||
} else {
|
||||
resourceId = theResource.getId();
|
||||
|
@ -1874,7 +2018,7 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
if (Character.isDigit(theResource.getId().getIdPart().charAt(0))) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
|
||||
}
|
||||
return doCreate(theResource, null, true);
|
||||
return doCreate(theResource, null, thePerformIndexing);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,10 @@ public class FhirSystemDaoDstu2 extends BaseFhirSystemDao<Bundle> {
|
|||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
if (parts.getResourceId() != null) {
|
||||
// if (res.getId().hasIdPart() && isBlank(parts.getResourceId())) {
|
||||
// parts.setResourceId(res.getId().getIdPart());
|
||||
// }
|
||||
if (isNotBlank(parts.getResourceId())) {
|
||||
res.setId(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
outcome = resourceDao.update(res, null, false);
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,9 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
class HistoryTuple implements Comparable<HistoryTuple> {
|
||||
|
||||
private Long myId;
|
||||
|
@ -64,4 +67,13 @@ class HistoryTuple implements Comparable<HistoryTuple> {
|
|||
myUpdated = theUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
b.append("id", myId);
|
||||
b.append("history", myIsHistory);
|
||||
b.append("updated", myUpdated);
|
||||
return b.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -446,6 +446,22 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
|
|||
}
|
||||
systems.add(null);
|
||||
codes.add(nextValue.getValueAsString());
|
||||
} else if (nextObject instanceof CodingDt) {
|
||||
CodingDt nextValue = (CodingDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String nextSystem = nextValue.getSystemElement().getValueAsString();
|
||||
String nextCode = nextValue.getCodeElement().getValue();
|
||||
if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
|
||||
systems.add(nextSystem);
|
||||
codes.add(nextCode);
|
||||
}
|
||||
|
||||
if (!nextValue.getDisplayElement().isEmpty()) {
|
||||
systems.add(null);
|
||||
codes.add(nextValue.getDisplayElement().getValue());
|
||||
}
|
||||
} else if (nextObject instanceof CodeableConceptDt) {
|
||||
CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
|
||||
if (!nextCC.getTextElement().isEmpty()) {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
-->
|
||||
</bean>
|
||||
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
<property name="jpaVendorAdapter">
|
||||
|
@ -41,7 +41,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
@ -217,8 +218,8 @@ public class FhirResourceDaoDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithIfNoneExist() {
|
||||
String methodName = "testCreateWithIfNoneExist";
|
||||
public void testCreateWithIfNoneExistBasic() {
|
||||
String methodName = "testCreateWithIfNoneExistBasic";
|
||||
MethodOutcome results;
|
||||
|
||||
Patient p = new Patient();
|
||||
|
@ -1522,6 +1523,195 @@ public class FhirResourceDaoDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingString() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// String Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
StringParam param = new StringParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_FAMILY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
StringParam param = new StringParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_FAMILY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingQuantity() {
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
obs.setValue(new QuantityDt(123));
|
||||
notMissing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Quantity Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
QuantityParam param = new QuantityParam();
|
||||
param.setMissing(false);
|
||||
params.put(Observation.SP_VALUE_QUANTITY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourObservationDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
QuantityParam param = new QuantityParam();
|
||||
param.setMissing(true);
|
||||
params.put(Observation.SP_VALUE_QUANTITY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourObservationDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithToken() {
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
obs.getCode().addCoding().setSystem("urn:system").setCode("002");
|
||||
notMissing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Token Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
TokenParam param = new TokenParam();
|
||||
param.setMissing(false);
|
||||
params.put(Observation.SP_CODE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourObservationDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
TokenParam param = new TokenParam();
|
||||
param.setMissing(true);
|
||||
params.put(Observation.SP_CODE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourObservationDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingDate() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Date Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
DateParam param = new DateParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_BIRTHDATE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
DateParam param = new DateParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_BIRTHDATE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingReference() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Reference Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
ReferenceParam param = new ReferenceParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_ORGANIZATION, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
ReferenceParam param = new ReferenceParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_ORGANIZATION, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchStringParamWithNonNormalized() {
|
||||
{
|
||||
|
@ -2233,36 +2423,36 @@ public class FhirResourceDaoDstu2Test {
|
|||
@Test
|
||||
public void testUpdateMaintainsSearchParams() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2AAA");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2AAA");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2BBB");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB");
|
||||
ourPatientDao.create(p2).getId();
|
||||
|
||||
Set<Long> ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
|
||||
Set<Long> ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA"));
|
||||
assertEquals(1, ids.size());
|
||||
assertThat(ids, contains(p1id.getIdPartAsLong()));
|
||||
|
||||
// Update the name
|
||||
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsDstu2BBB");
|
||||
MethodOutcome update2 = ourPatientDao.update(p1);
|
||||
IdDt p1id2 = update2.getId();
|
||||
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA"));
|
||||
assertEquals(0, ids.size());
|
||||
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsBBB"));
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2BBB"));
|
||||
assertEquals(2, ids.size());
|
||||
|
||||
// Make sure vreads work
|
||||
p1 = ourPatientDao.read(p1id);
|
||||
assertEquals("testUpdateMaintainsSearchParamsAAA", p1.getNameFirstRep().getGivenAsSingleString());
|
||||
assertEquals("testUpdateMaintainsSearchParamsDstu2AAA", p1.getNameFirstRep().getGivenAsSingleString());
|
||||
|
||||
p1 = ourPatientDao.read(p1id2);
|
||||
assertEquals("testUpdateMaintainsSearchParamsBBB", p1.getNameFirstRep().getGivenAsSingleString());
|
||||
assertEquals("testUpdateMaintainsSearchParamsDstu2BBB", p1.getNameFirstRep().getGivenAsSingleString());
|
||||
|
||||
}
|
||||
|
||||
|
@ -2344,14 +2534,12 @@ public class FhirResourceDaoDstu2Test {
|
|||
FhirSystemDaoDstu2Test.doDeleteEverything(ourSystemDao);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchWithNoResults() {
|
||||
Device dev = new Device();
|
||||
dev.addIdentifier().setSystem("Foo");
|
||||
ourDeviceDao.create(dev);
|
||||
|
||||
|
||||
IBundleProvider value = ourDeviceDao.search(new SearchParameterMap());
|
||||
ourLog.info("Initial size: " + value.size());
|
||||
for (IBaseResource next : value.getResources(0, value.size())) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.containsString;
|
|||
import static org.hamcrest.Matchers.emptyString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
@ -11,10 +12,11 @@ import static org.junit.Assert.assertNull;
|
|||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
@ -23,10 +25,12 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderTest;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
|
@ -95,6 +99,30 @@ public class FhirSystemDaoDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderTest.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
||||
String bundleStr = IOUtils.toString(bundleRes);
|
||||
Bundle bundle = ourFhirContext.newXmlParser().parseResource(Bundle.class, bundleStr);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(bundle);
|
||||
|
||||
ourLog.info(ourFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) resp.getEntry().get(0).getResource();
|
||||
assertThat(oo.getIssue().get(0).getDetailsElement().getValue(), containsString("Transaction completed"));
|
||||
|
||||
assertThat(resp.getEntry().get(1).getTransactionResponse().getLocation(), startsWith("Patient/a555-44-4444/_history/"));
|
||||
assertThat(resp.getEntry().get(2).getTransactionResponse().getLocation(), startsWith("Patient/temp6789/_history/"));
|
||||
assertThat(resp.getEntry().get(3).getTransactionResponse().getLocation(), startsWith("Organization/GHH/_history/"));
|
||||
|
||||
Patient p = ourPatientDao.read(new IdDt("Patient/a555-44-4444/_history/1"));
|
||||
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference().getValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionReadAndSearch() {
|
||||
String methodName = "testTransactionReadAndSearch";
|
||||
|
@ -489,12 +517,12 @@ public class FhirSystemDaoDstu2Test {
|
|||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("urn:"+methodName);
|
||||
p.setId(methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getCode().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/urn:"+methodName);
|
||||
o.getSubject().setReference("Patient/"+methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
|
|
|
@ -4,7 +4,15 @@ import static org.hamcrest.Matchers.*;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
|
@ -13,6 +21,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
@ -32,11 +41,14 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import com.google.common.net.UrlEscapers;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
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.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.Device;
|
||||
|
@ -89,6 +101,7 @@ public class ResourceProviderDstu2Test {
|
|||
private static DaoConfig ourDaoConfig;
|
||||
private static CloseableHttpClient ourHttpClient;
|
||||
private static String ourServerBase;
|
||||
private static int ourPort;
|
||||
|
||||
// private static JpaConformanceProvider ourConfProvider;
|
||||
|
||||
|
@ -142,6 +155,7 @@ public class ResourceProviderDstu2Test {
|
|||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?name=" + methodName);
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdDt id;
|
||||
|
@ -161,7 +175,7 @@ public class ResourceProviderDstu2Test {
|
|||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertEquals(id.getValue(), newIdString);
|
||||
assertEquals(id.getValue(), newIdString); // version should match for conditional create
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
@ -176,7 +190,7 @@ public class ResourceProviderDstu2Test {
|
|||
pt.addName().addFamily(methodName);
|
||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient?name=" + methodName);
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdDt id;
|
||||
|
@ -195,7 +209,7 @@ public class ResourceProviderDstu2Test {
|
|||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
IdDt newId = new IdDt(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue());
|
||||
assertEquals(id.toVersionless(), newId.toVersionless());
|
||||
assertEquals(id.toVersionless(), newId.toVersionless()); // version shouldn't match for conditional update
|
||||
assertNotEquals(id, newId);
|
||||
} finally {
|
||||
response.close();
|
||||
|
@ -204,8 +218,8 @@ public class ResourceProviderDstu2Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteResourceConditional() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional";
|
||||
public void testDeleteResourceConditional1() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional1";
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
|
@ -243,6 +257,67 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on email from Rene Spronk
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteResourceConditional2() throws IOException, Exception {
|
||||
String methodName = "testDeleteResourceConditional2";
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.addName().addFamily(methodName);
|
||||
pt.addIdentifier().setSystem("http://ghh.org/patient").setValue("555-44-4444");
|
||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
IdDt id;
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL
|
||||
* but we want to make sure that works too..
|
||||
*/
|
||||
Socket sock = new Socket();
|
||||
try {
|
||||
sock.connect(new InetSocketAddress("localhost", ourPort));
|
||||
sock.getOutputStream().write(("DELETE " + "/fhir/context/Patient?identifier=" + ("http://ghh.org/patient|555-44-4444")).getBytes("UTF-8"));
|
||||
sock.getOutputStream().write("\n\n".getBytes("UTF-8"));
|
||||
sock.getOutputStream().flush();
|
||||
|
||||
InputStream inputStream = sock.getInputStream();
|
||||
|
||||
byte[] buf = new byte[10000];
|
||||
int count;
|
||||
StringBuilder b = new StringBuilder();
|
||||
while ((count = inputStream.read(buf)) != -1) {
|
||||
b.append(new String(buf, 0, count, Charset.forName("UTF-8")));
|
||||
}
|
||||
String resp = b.toString();
|
||||
|
||||
ourLog.info("Resp: {}", resp);
|
||||
} finally {
|
||||
sock.close();
|
||||
}
|
||||
HttpGet read = new HttpGet(ourServerBase + "/Patient/" + id.getIdPart());
|
||||
response = ourHttpClient.execute(read);
|
||||
try {
|
||||
ourLog.info(response.toString());
|
||||
assertEquals(Constants.STATUS_HTTP_410_GONE, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for issue #60
|
||||
*/
|
||||
|
@ -313,6 +388,59 @@ public class ResourceProviderDstu2Test {
|
|||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testSearchWithMissing() throws Exception {
|
||||
String methodName = "testSearchWithMissing";
|
||||
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
org.setName(methodName + "name");
|
||||
IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(false))
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + ": " + list.toString());
|
||||
assertThat(list, containsInRelativeOrder(orgNotMissing));
|
||||
assertThat(list, not(containsInRelativeOrder(orgMissing)));
|
||||
}
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(true))
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(methodName + ": " + list.toString());
|
||||
assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
|
||||
assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
|
||||
}
|
||||
}
|
||||
|
||||
private List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {
|
||||
List<IdDt> list = new ArrayList<IdDt>();
|
||||
for (BundleEntry next : found.getEntries()) {
|
||||
list.add(next.getResource().getId().toUnqualifiedVersionless());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverythingOperation() throws Exception {
|
||||
String methodName = "testEverythingOperation";
|
||||
|
@ -802,13 +930,13 @@ public class ResourceProviderDstu2Test {
|
|||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
|
||||
RestfulServer restServer = new RestfulServer();
|
||||
ourFhirCtx = FhirContext.forDstu2();
|
||||
restServer.setFhirContext(ourFhirCtx);
|
||||
|
||||
ourServerBase = "http://localhost:" + port + "/fhir/context";
|
||||
ourServerBase = "http://localhost:" + ourPort + "/fhir/context";
|
||||
|
||||
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
|
||||
|
@ -826,7 +954,7 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
restServer.setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||
|
||||
ourServer = new Server(port);
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||
proxyHandler.setContextPath("/");
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
@ -15,25 +16,22 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1;
|
||||
import ca.uhn.fhir.jpa.rp.dstu.ObservationResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu.OrganizationResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu.PatientResourceProvider;
|
||||
import ca.uhn.fhir.jpa.provider.QuestionnaireResourceProvider;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
||||
public class SystemProviderTest {
|
||||
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderTest.class);
|
||||
private static Server ourServer;
|
||||
private static ClassPathXmlApplicationContext ourAppCtx;
|
||||
private static FhirContext ourCtx;
|
||||
|
@ -42,14 +40,48 @@ public class SystemProviderTest {
|
|||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderTest.class.getResourceAsStream("/test-server-seed-bundle.json");
|
||||
Bundle bundle = FhirContext.forDstu1().newJsonParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourClient.transaction().withResources(res).execute();
|
||||
|
||||
InputStream bundleRes = SystemProviderTest.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle2() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderTest.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
Bundle resp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
IdDt id1_1 = new IdDt(resp.getEntry().get(1).getTransactionResponse().getLocation());
|
||||
assertEquals("Provenance", id1_1.getResourceType());
|
||||
IdDt id1_2 = new IdDt(resp.getEntry().get(2).getTransactionResponse().getLocation());
|
||||
IdDt id1_3 = new IdDt(resp.getEntry().get(3).getTransactionResponse().getLocation());
|
||||
IdDt id1_4 = new IdDt(resp.getEntry().get(4).getTransactionResponse().getLocation());
|
||||
|
||||
/*
|
||||
* Same bundle!
|
||||
*/
|
||||
|
||||
bundleRes = SystemProviderTest.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
bundle = IOUtils.toString(bundleRes);
|
||||
response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
resp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
IdDt id2_1 = new IdDt(resp.getEntry().get(1).getTransactionResponse().getLocation());
|
||||
IdDt id2_2 = new IdDt(resp.getEntry().get(2).getTransactionResponse().getLocation());
|
||||
IdDt id2_3 = new IdDt(resp.getEntry().get(3).getTransactionResponse().getLocation());
|
||||
IdDt id2_4 = new IdDt(resp.getEntry().get(4).getTransactionResponse().getLocation());
|
||||
|
||||
assertNotEquals(id1_1.toVersionless(), id2_1.toVersionless());
|
||||
assertEquals("Provenance", id2_1.getResourceType());
|
||||
assertEquals(id1_2.toVersionless(), id2_2.toVersionless());
|
||||
assertEquals(id1_3.toVersionless(), id2_3.toVersionless());
|
||||
assertEquals(id1_4.toVersionless(), id2_4.toVersionless());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
|
@ -60,28 +92,28 @@ public class SystemProviderTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourAppCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml", "hapi-fhir-server-resourceproviders-dstu1.xml");
|
||||
ourAppCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml", "hapi-fhir-server-resourceproviders-dstu2.xml");
|
||||
|
||||
IFhirResourceDao<Patient> patientDao = (IFhirResourceDao<Patient>) ourAppCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
|
||||
IFhirResourceDao<Patient> patientDao = (IFhirResourceDao<Patient>) ourAppCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
|
||||
PatientResourceProvider patientRp = new PatientResourceProvider();
|
||||
patientRp.setDao(patientDao);
|
||||
|
||||
IFhirResourceDao<Questionnaire> questionnaireDao = (IFhirResourceDao<Questionnaire>) ourAppCtx.getBean("myQuestionnaireDaoDstu1", IFhirResourceDao.class);
|
||||
IFhirResourceDao<Questionnaire> questionnaireDao = (IFhirResourceDao<Questionnaire>) ourAppCtx.getBean("myQuestionnaireDaoDstu2", IFhirResourceDao.class);
|
||||
QuestionnaireResourceProvider questionnaireRp = new QuestionnaireResourceProvider();
|
||||
questionnaireRp.setDao(questionnaireDao);
|
||||
|
||||
IFhirResourceDao<Observation> observationDao = (IFhirResourceDao<Observation>) ourAppCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
|
||||
IFhirResourceDao<Observation> observationDao = (IFhirResourceDao<Observation>) ourAppCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
|
||||
ObservationResourceProvider observationRp = new ObservationResourceProvider();
|
||||
observationRp.setDao(observationDao);
|
||||
|
||||
IFhirResourceDao<Organization> organizationDao = (IFhirResourceDao<Organization>) ourAppCtx.getBean("myOrganizationDaoDstu1", IFhirResourceDao.class);
|
||||
IFhirResourceDao<Organization> organizationDao = (IFhirResourceDao<Organization>) ourAppCtx.getBean("myOrganizationDaoDstu2", IFhirResourceDao.class);
|
||||
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
||||
organizationRp.setDao(organizationDao);
|
||||
|
||||
RestfulServer restServer = new RestfulServer();
|
||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
|
||||
|
||||
JpaSystemProviderDstu1 systemProv = ourAppCtx.getBean(JpaSystemProviderDstu1.class, "mySystemProviderDstu1");
|
||||
JpaSystemProviderDstu2 systemProv = ourAppCtx.getBean(JpaSystemProviderDstu2.class, "mySystemProviderDstu2");
|
||||
restServer.setPlainProviders(systemProv);
|
||||
|
||||
int myPort = RandomServerPortProvider.findFreePort();
|
||||
|
@ -96,10 +128,12 @@ public class SystemProviderTest {
|
|||
servletHolder.setServlet(restServer);
|
||||
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
|
||||
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
restServer.setFhirContext(ourCtx);
|
||||
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
ourCtx = restServer.getFhirContext();
|
||||
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(600 * 1000);
|
||||
ourClient = ourCtx.newRestfulGenericClient(serverBase);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
-->
|
||||
</bean>
|
||||
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
<property name="jpaVendorAdapter">
|
||||
|
@ -43,7 +43,7 @@
|
|||
</property>
|
||||
</bean>
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -1,690 +0,0 @@
|
|||
|
||||
{
|
||||
"resourceType":"Bundle",
|
||||
"entry":[
|
||||
{
|
||||
"deleted":null,
|
||||
"title":"Patient http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/Patient/5556918",
|
||||
"id":"Patient/5556918",
|
||||
"link":[
|
||||
{
|
||||
"rel":"self",
|
||||
"href":"Patient/5556918"
|
||||
}
|
||||
],
|
||||
"published":"2014-05-29T10:49:32-04:00",
|
||||
"content":{
|
||||
"resourceType":"Patient",
|
||||
"id":"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/Patient/5556918",
|
||||
"text":{
|
||||
"status":"generated",
|
||||
"div":"<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> Donald null <b>DUCK </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>7000135</td></tr><tr><td>Address</td><td><span>10 Duxon Street </span><br/><span>VICTORIA </span><span>BC </span><span>Can </span></td></tr><tr><td>Date of birth</td><td><span>01 June 1980</span></td></tr></tbody></table></div>"
|
||||
},
|
||||
"identifier":[
|
||||
{
|
||||
"use":"official",
|
||||
"label":"University Health Network MRN 7000135",
|
||||
"system":"urn:oid:2.16.840.1.113883.3.239.18.148",
|
||||
"value":"7000135",
|
||||
"assigner":{
|
||||
"resource":"Organization/1.3.6.1.4.1.12201"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name":[
|
||||
{
|
||||
"family":[
|
||||
"Duck"
|
||||
],
|
||||
"given":[
|
||||
"Donald"
|
||||
]
|
||||
}
|
||||
],
|
||||
"telecom":[
|
||||
{
|
||||
"system":"phone",
|
||||
"use":"home"
|
||||
},
|
||||
{
|
||||
"system":"phone",
|
||||
"use":"work"
|
||||
},
|
||||
{
|
||||
"system":"phone",
|
||||
"use":"mobile"
|
||||
},
|
||||
{
|
||||
"system":"email",
|
||||
"use":"home"
|
||||
}
|
||||
],
|
||||
"gender":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"http://hl7.org/fhir/v3/AdministrativeGender",
|
||||
"code":"M"
|
||||
}
|
||||
]
|
||||
},
|
||||
"birthDate":"1980-06-01T00:00:00",
|
||||
"address":[
|
||||
{
|
||||
"use":"home",
|
||||
"line":[
|
||||
"10 Duxon Street"
|
||||
],
|
||||
"city":"VICTORIA",
|
||||
"state":"BC",
|
||||
"zip":"V8N 1Y4",
|
||||
"country":"Can"
|
||||
}
|
||||
],
|
||||
"managingOrganization":{
|
||||
"resource":"Organization/1.3.6.1.4.1.12201"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"deleted":null,
|
||||
"title":"DiagnosticReport http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/DiagnosticReport/5978827",
|
||||
"id":"DiagnosticReport/5978827",
|
||||
"link":[
|
||||
{
|
||||
"rel":"self",
|
||||
"href":"DiagnosticReport/5978827"
|
||||
}
|
||||
],
|
||||
"published":"2014-05-29T10:49:33-04:00",
|
||||
"content":{
|
||||
"resourceType":"DiagnosticReport",
|
||||
"id":"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/DiagnosticReport/5978827",
|
||||
"text":{
|
||||
"status":"generated",
|
||||
"div":"<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> C&S </div><table class=\"hapiPropertyTable\"><tbody><tr><td>Status</td><td>partial</td></tr><tr><td>Issued</td><td> 29 April 2014 17:21:56 </td></tr></tbody></table><table class=\"hapiTableOfValues\"><thead><tr><td>Name</td><td>Value</td><td>Interpretation</td><td>Reference Range</td><td>Status</td></tr></thead><tbody><tr class=\"hapiTableOfValuesRowEven\"><td> Collection Info </td><td> Spec #102758: 26 Sep 08 1117</td><td/><td/><td>preliminary</td></tr><tr class=\"hapiTableOfValuesRowOdd\"><td> Direct Stain </td><td> pus cells</td><td/><td/><td>preliminary</td></tr><tr class=\"hapiTableOfValuesRowEven\"><td> Header </td><td> To view Culture & Sensitivity Results, select</td><td/><td/><td/></tr><tr class=\"hapiTableOfValuesRowOdd\"><td> Header </td><td> (Y) Report Query. Do NOT select number beside</td><td/><td/><td/></tr><tr class=\"hapiTableOfValuesRowEven\"><td> Header </td><td> Prelim or Final Result field, as there is</td><td/><td/><td/></tr><tr class=\"hapiTableOfValuesRowOdd\"><td> Header </td><td> potential for viewing an incomplete report.</td><td/><td/><td/></tr><tr class=\"hapiTableOfValuesRowEven\"><td> Organism </td><td> Haemophilus influenzae</td><td/><td/><td>final</td></tr><tr class=\"hapiTableOfValuesRowOdd\"><td> Qualifier </td><td> =>10 x E6 cfu/L SIGNIFICANT RESULT. Organisms cultured in quantities =>10 x E6 cfu/L are consistent with pneumonia. beta-lactamase positive result suggests resistance to ampicillin but generally susceptible to amoxicillin- clavulanic and cefuroxime.</td><td/><td/><td>final</td></tr><tr class=\"hapiTableOfValuesRowEven\"><td> Sensitivities </td><td> _Beta-lactamase Pos: </td><td/><td/><td>final</td></tr><tr class=\"hapiTableOfValuesRowOdd\"><td> Test Comment </td><td> =>10 x E6 cfu/L Commensal flora</td><td/><td/><td>final</td></tr></tbody></table></div>"
|
||||
},
|
||||
"contained":[
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"f816a276-cfad-4eca-a9fa-f1dff844a196",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"146151.1"
|
||||
}
|
||||
],
|
||||
"text":"Collection Info"
|
||||
},
|
||||
"valueString":"Spec #102758: 26 Sep 08 1117",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"preliminary"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"23b55496-1c2a-4d5f-9c24-8ca5042f4027",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"GM.2"
|
||||
}
|
||||
],
|
||||
"text":"Direct Stain"
|
||||
},
|
||||
"valueString":"pus cells",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"preliminary"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"74e6791a-d810-4545-8410-e9eca41e81d6",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H1.3"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"To view Culture & Sensitivity Results, select",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"cd8c6a6c-7ef5-446f-b07b-47a21bfe28ee",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H2.4"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"(Y) Report Query. Do NOT select number beside",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"4a3d453d-3a18-432f-8f1f-d7657c50dcd4",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H3.5"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"Prelim or Final Result field, as there is",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"0dd6cff6-f9db-42cc-89c9-2cd6ba6fe5af",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H4.6"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"potential for viewing an incomplete report.",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"6d6b0117-220f-4b9a-abf3-5faf772cfa61",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/O.4"
|
||||
}
|
||||
],
|
||||
"text":"Organism"
|
||||
},
|
||||
"valueString":"Haemophilus influenzae",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"64068acf-57f4-42c8-b0e6-416247067b16",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/31266.5"
|
||||
}
|
||||
],
|
||||
"text":"Qualifier"
|
||||
},
|
||||
"valueString":"=>10 x E6 cfu/L SIGNIFICANT RESULT. Organisms cultured in quantities =>10 x E6 cfu/L are consistent with pneumonia. beta-lactamase positive result suggests resistance to ampicillin but generally susceptible to amoxicillin- clavulanic and cefuroxime.",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"0f9d254f-3ad1-404b-9be9-20258b3c242f",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/31415.6"
|
||||
}
|
||||
],
|
||||
"text":"Sensitivities"
|
||||
},
|
||||
"valueString":"_Beta-lactamase Pos: ",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"349bb02b-fbbe-4ce0-b190-3f545240dcc0",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"Q.3"
|
||||
}
|
||||
],
|
||||
"text":"Test Comment"
|
||||
},
|
||||
"valueString":"=>10 x E6 cfu/L Commensal flora",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"f816a276-cfad-4eca-a9fa-f1dff844a196",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"146151.1"
|
||||
}
|
||||
],
|
||||
"text":"Collection Info"
|
||||
},
|
||||
"valueString":"Spec #102758: 26 Sep 08 1117",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"preliminary"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"23b55496-1c2a-4d5f-9c24-8ca5042f4027",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"GM.2"
|
||||
}
|
||||
],
|
||||
"text":"Direct Stain"
|
||||
},
|
||||
"valueString":"pus cells",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"preliminary"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"74e6791a-d810-4545-8410-e9eca41e81d6",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H1.3"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"To view Culture & Sensitivity Results, select",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"cd8c6a6c-7ef5-446f-b07b-47a21bfe28ee",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H2.4"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"(Y) Report Query. Do NOT select number beside",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"4a3d453d-3a18-432f-8f1f-d7657c50dcd4",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H3.5"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"Prelim or Final Result field, as there is",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"0dd6cff6-f9db-42cc-89c9-2cd6ba6fe5af",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"1H4.6"
|
||||
}
|
||||
],
|
||||
"text":"Header"
|
||||
},
|
||||
"valueString":"potential for viewing an incomplete report.",
|
||||
"issued":"2014-04-29T17:21:56"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"6d6b0117-220f-4b9a-abf3-5faf772cfa61",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/O.4"
|
||||
}
|
||||
],
|
||||
"text":"Organism"
|
||||
},
|
||||
"valueString":"Haemophilus influenzae",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"64068acf-57f4-42c8-b0e6-416247067b16",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/31266.5"
|
||||
}
|
||||
],
|
||||
"text":"Qualifier"
|
||||
},
|
||||
"valueString":"=>10 x E6 cfu/L SIGNIFICANT RESULT. Organisms cultured in quantities =>10 x E6 cfu/L are consistent with pneumonia. beta-lactamase positive result suggests resistance to ampicillin but generally susceptible to amoxicillin- clavulanic and cefuroxime.",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"0f9d254f-3ad1-404b-9be9-20258b3c242f",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"F/31415.6"
|
||||
}
|
||||
],
|
||||
"text":"Sensitivities"
|
||||
},
|
||||
"valueString":"_Beta-lactamase Pos: ",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"A"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
},
|
||||
{
|
||||
"resourceType":"Observation",
|
||||
"id":"349bb02b-fbbe-4ce0-b190-3f545240dcc0",
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.6",
|
||||
"code":"Q.3"
|
||||
}
|
||||
],
|
||||
"text":"Test Comment"
|
||||
},
|
||||
"valueString":"=>10 x E6 cfu/L Commensal flora",
|
||||
"interpretation":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"N"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"status":"final"
|
||||
}
|
||||
],
|
||||
"name":{
|
||||
"coding":[
|
||||
{
|
||||
"system":"urn:oid:1.3.6.1.4.1.12201.102.5",
|
||||
"code":"4140"
|
||||
}
|
||||
],
|
||||
"text":"C&S"
|
||||
},
|
||||
"status":"partial",
|
||||
"issued":"2014-04-29T17:21:56",
|
||||
"subject":{
|
||||
"resource":"Patient/5556918"
|
||||
},
|
||||
"identifier":{
|
||||
"value":"2363922"
|
||||
},
|
||||
"diagnosticDateTime":"2014-04-14T00:00:00-04:00",
|
||||
"result":[
|
||||
{
|
||||
"resource":"#f816a276-cfad-4eca-a9fa-f1dff844a196"
|
||||
},
|
||||
{
|
||||
"resource":"#23b55496-1c2a-4d5f-9c24-8ca5042f4027"
|
||||
},
|
||||
{
|
||||
"resource":"#74e6791a-d810-4545-8410-e9eca41e81d6"
|
||||
},
|
||||
{
|
||||
"resource":"#cd8c6a6c-7ef5-446f-b07b-47a21bfe28ee"
|
||||
},
|
||||
{
|
||||
"resource":"#4a3d453d-3a18-432f-8f1f-d7657c50dcd4"
|
||||
},
|
||||
{
|
||||
"resource":"#0dd6cff6-f9db-42cc-89c9-2cd6ba6fe5af"
|
||||
},
|
||||
{
|
||||
"resource":"#6d6b0117-220f-4b9a-abf3-5faf772cfa61"
|
||||
},
|
||||
{
|
||||
"resource":"#64068acf-57f4-42c8-b0e6-416247067b16"
|
||||
},
|
||||
{
|
||||
"resource":"#0f9d254f-3ad1-404b-9be9-20258b3c242f"
|
||||
},
|
||||
{
|
||||
"resource":"#349bb02b-fbbe-4ce0-b190-3f545240dcc0"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"deleted":null,
|
||||
"title":"Organization http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/Organization/1.3.6.1.4.1.12201",
|
||||
"id":"Organization/1.3.6.1.4.1.12201",
|
||||
"link":[
|
||||
{
|
||||
"rel":"self",
|
||||
"href":"Organization/1.3.6.1.4.1.12201"
|
||||
}
|
||||
],
|
||||
"published":"2014-05-29T10:49:32-04:00",
|
||||
"content":{
|
||||
"resourceType":"Organization",
|
||||
"id":"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.0/Organization/1.3.6.1.4.1.12201",
|
||||
"extension":[
|
||||
{
|
||||
"url":"http://fhir.connectinggta.ca/Profile/organization#providerIdPool",
|
||||
"valueUri":"1.3.6.1.4.1.12201.1"
|
||||
}
|
||||
],
|
||||
"text":{
|
||||
"status":"empty",
|
||||
"div":"<div xmlns=\"http://www.w3.org/1999/xhtml\">No narrative template available for resource profile: http://fhir.connectinggta.ca/Profile/organization</div>"
|
||||
},
|
||||
"contained":[
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.1",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.1"
|
||||
},
|
||||
"name":"Toronto General Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.2",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.2"
|
||||
},
|
||||
"name":"Toronto Western Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.3",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.3"
|
||||
},
|
||||
"name":"Princess Margaret Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.4",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.4"
|
||||
},
|
||||
"name":"Toronto Rehab Institute"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.1",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.1"
|
||||
},
|
||||
"name":"Toronto General Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.2",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.2"
|
||||
},
|
||||
"name":"Toronto Western Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.3",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.3"
|
||||
},
|
||||
"name":"Princess Margaret Hospital"
|
||||
},
|
||||
{
|
||||
"resourceType":"Location",
|
||||
"id":"1.3.6.1.4.1.12201.100.4",
|
||||
"identifier":{
|
||||
"system":"urn:cgta:facility_ids",
|
||||
"value":"1.3.6.1.4.1.12201.100.4"
|
||||
},
|
||||
"name":"Toronto Rehab Institute"
|
||||
}
|
||||
],
|
||||
"name":"University Health Network",
|
||||
"type":{
|
||||
"coding":[
|
||||
{
|
||||
"code":"HOSPITAL"
|
||||
}
|
||||
]
|
||||
},
|
||||
"address":[
|
||||
{
|
||||
"line":[
|
||||
"R. Fraser Elliott Building, 1st Floor",
|
||||
"190 Elizabeth St."
|
||||
],
|
||||
"city":"Toronto",
|
||||
"state":"ON",
|
||||
"zip":"M5G 2C4"
|
||||
}
|
||||
],
|
||||
"location":[
|
||||
{
|
||||
"resource":"#1.3.6.1.4.1.12201.100.1"
|
||||
},
|
||||
{
|
||||
"resource":"#1.3.6.1.4.1.12201.100.2"
|
||||
},
|
||||
{
|
||||
"resource":"#1.3.6.1.4.1.12201.100.3"
|
||||
},
|
||||
{
|
||||
"resource":"#1.3.6.1.4.1.12201.100.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="a130877d-a636-4993-97e6-0eeb7734e5"/>
|
||||
<type value="transaction"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<!-- PID|||555-44-4444||EVERYWOMAN^EVE^E^^^^L|JONES|19620320|F|||153 FERNWOOD DR.^
|
||||
^STATESVILLE^OH^35292||(206)3345232|(206)752-121||||AC555444444||67-A4335^OH^20030520 -->
|
||||
<id value="a555-44-4444"/>
|
||||
<extension url="http://ihe.net/ITI-78/Profile/pdqm#mothersMaidenName">
|
||||
<valueHumanName>
|
||||
<family value="Jones"/>
|
||||
</valueHumanName>
|
||||
</extension>
|
||||
<identifier>
|
||||
<use value="official"/>
|
||||
<system value="http://ghh.org/patient"/>
|
||||
<value value="555-44-4444"/>
|
||||
</identifier>
|
||||
<identifier>
|
||||
<use value="official"/>
|
||||
<system value="http://www.ohio.gov/dmv/driverslicence"/>
|
||||
<value value="67-A4335"/>
|
||||
<period>
|
||||
<end value="2003-05-20"/>
|
||||
</period>
|
||||
</identifier>
|
||||
<name>
|
||||
<use value="official"/>
|
||||
<family value="Everywoman"/>
|
||||
<given value="Eve E."/>
|
||||
</name>
|
||||
<telecom>
|
||||
<system value="phone"/>
|
||||
<value value="(206)3345232"/>
|
||||
<use value="home"/>
|
||||
</telecom>
|
||||
<telecom>
|
||||
<system value="phone"/>
|
||||
<value value="(206)752-121"/>
|
||||
<use value="work"/>
|
||||
</telecom>
|
||||
<gender value="female"/>
|
||||
<birthDate value="1962-03-20"/>
|
||||
<address>
|
||||
<line value="153 Fernwood Dr."/>
|
||||
<city value="Statesville"/>
|
||||
<state value="OH"/>
|
||||
<postalCode value="35292"/>
|
||||
</address>
|
||||
<managingOrganization>
|
||||
<reference value="Organization/GHH"/>
|
||||
<display value="Good Health Hospital"/>
|
||||
</managingOrganization>
|
||||
<link>
|
||||
<other>
|
||||
<reference value="Patient/temp6789"/>
|
||||
</other>
|
||||
<type value="seealso"/>
|
||||
</link>
|
||||
<active value="true"/>
|
||||
</Patient>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="PUT"/>
|
||||
<url value="Patient/a555-44-4444"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<!-- Jane Doe registered in the emergency department -->
|
||||
<id value="temp6789"/>
|
||||
<identifier>
|
||||
<use value="temp"/>
|
||||
<system value="http://ghh.org/patient"/>
|
||||
<value value="temp6789"/>
|
||||
</identifier>
|
||||
<name>
|
||||
<use value="temp"/>
|
||||
<family value="Doe 6789"/>
|
||||
<given value="Jane"/>
|
||||
</name>
|
||||
<gender value="female"/>
|
||||
<managingOrganization>
|
||||
<reference value="Organization/GHH"/>
|
||||
<display value="Good Health Hospital"/>
|
||||
</managingOrganization>
|
||||
<link>
|
||||
<other>
|
||||
<reference value="Patient/a555-44-4444"/>
|
||||
</other>
|
||||
<type value="replace"/>
|
||||
</link>
|
||||
<active value="true"/>
|
||||
</Patient>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="PUT"/>
|
||||
<url value="Patient/temp6789"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
<entry>
|
||||
<resource>
|
||||
<Organization>
|
||||
<id value="GHH"/>
|
||||
</Organization>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="PUT"/>
|
||||
<url value="Organization/GHH"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -0,0 +1,168 @@
|
|||
<!-- Example Provided by Rene Spronk -->
|
||||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="ringholm1430996763590912"/>
|
||||
<type value="transaction"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Provenance>
|
||||
<id value="ringholm1430996763591053"/>
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">Authored on 15-Feb 2015 by GHH.</div>
|
||||
</text>
|
||||
<target>
|
||||
<!-- unversioned, part of a transaction -->
|
||||
<reference value="Patient/555-44-4444"/>
|
||||
</target>
|
||||
<recorded value="2015-05-07T13:06:03+01:00"/>
|
||||
<reason>
|
||||
<text value="Patient validated demographics."/>
|
||||
</reason>
|
||||
<agent>
|
||||
<role>
|
||||
<system value="http://hl7.org/fhir/provenance-participant-role"/>
|
||||
<code value="author"/>
|
||||
</role>
|
||||
<type>
|
||||
<system value="http://hl7.org/fhir/provenance-participant-type"/>
|
||||
<code value="patient"/>
|
||||
</type>
|
||||
<referenceReference>
|
||||
<reference value="Patient/555-44-4444"/>
|
||||
<display value="Patient Everywoman"/>
|
||||
</referenceReference>
|
||||
<display value="Eve Everywoman"/>
|
||||
</agent>
|
||||
</Provenance>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="POST"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<id value="555-44-4444"/>
|
||||
<extension url="http://ihe.net/ITI-78/Profile/pdqm#mothersMaidenName">
|
||||
<valueHumanName>
|
||||
<family value="Jones"/>
|
||||
</valueHumanName>
|
||||
</extension>
|
||||
<identifier>
|
||||
<use value="official"/>
|
||||
<system value="http://ghh.org/patient"/>
|
||||
<value value="555-44-4444"/>
|
||||
</identifier>
|
||||
<identifier>
|
||||
<use value="official"/>
|
||||
<system value="http://www.ohio.gov/dmv/driverslicence"/>
|
||||
<value value="67-A4335"/>
|
||||
<period>
|
||||
<end value="2003-05-20"/>
|
||||
</period>
|
||||
</identifier>
|
||||
<name>
|
||||
<use value="official"/>
|
||||
<family value="Everywoman"/>
|
||||
<given value="Eve E."/>
|
||||
</name>
|
||||
<telecom>
|
||||
<system value="phone"/>
|
||||
<value value="(206)3345232"/>
|
||||
<use value="home"/>
|
||||
</telecom>
|
||||
<telecom>
|
||||
<system value="phone"/>
|
||||
<value value="(206)752-121"/>
|
||||
<use value="work"/>
|
||||
</telecom>
|
||||
<gender value="female"/>
|
||||
<birthDate value="1962-03-20"/>
|
||||
<address>
|
||||
<line value="153 Fernwood Dr."/>
|
||||
<city value="Statesville"/>
|
||||
<state value="OH"/>
|
||||
<postalCode value="35292"/>
|
||||
</address>
|
||||
<managingOrganization>
|
||||
<reference value="Organization/GHH"/>
|
||||
<display value="Good Health Hospital"/>
|
||||
</managingOrganization>
|
||||
<link>
|
||||
<other>
|
||||
<reference value="Patient/temp6789"/>
|
||||
</other>
|
||||
<type value="seealso"/>
|
||||
</link>
|
||||
<active value="true"/>
|
||||
</Patient>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="PUT"/>
|
||||
<url value="Patient/?identifier=http://ghh.org/patient%7C555-44-4444"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<!-- Jane Doe registered in the emergency department -->
|
||||
<id value="temp6789"/>
|
||||
<identifier>
|
||||
<use value="temp"/>
|
||||
<system value="http://ghh.org/patient"/>
|
||||
<value value="temp6789"/>
|
||||
</identifier>
|
||||
<name>
|
||||
<use value="temp"/>
|
||||
<family value="Doe 6789"/>
|
||||
<given value="Jane"/>
|
||||
</name>
|
||||
<gender value="female"/>
|
||||
<managingOrganization>
|
||||
<reference value="Organization/GHH"/>
|
||||
<display value="Good Health Hospital"/>
|
||||
</managingOrganization>
|
||||
<link>
|
||||
<other>
|
||||
<reference value="Patient/555-44-4444"/>
|
||||
</other>
|
||||
<type value="replace"/>
|
||||
</link>
|
||||
<active value="true"/>
|
||||
</Patient>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="PUT"/>
|
||||
<url value="Patient/?identifier=http://ghh.org/patient%7Ctemp6789"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
<entry>
|
||||
<resource>
|
||||
<Organization>
|
||||
<id value="GHH"/>
|
||||
<identifier>
|
||||
<!-- Identifier for the GHH hospital -->
|
||||
<use value="official"/>
|
||||
<system value="http://ghh.org/department"/>
|
||||
<value value="GHH"/>
|
||||
</identifier>
|
||||
<name value="Good Health Hospital"/>
|
||||
<type>
|
||||
<!-- GHH is a Hospital -->
|
||||
<coding>
|
||||
<system value="http://snomed.info/sct"/>
|
||||
<code value="22232009"/>
|
||||
<display value="Hospital"/>
|
||||
</coding>
|
||||
</type>
|
||||
<active value="true"/>
|
||||
</Organization>
|
||||
</resource>
|
||||
<transaction>
|
||||
<method value="POST"/>
|
||||
<url value="Organization"/>
|
||||
<ifNoneExist value="Organization/?identifier=http://ghh.org/department%7CGHH"/>
|
||||
</transaction>
|
||||
</entry>
|
||||
</Bundle>
|
||||
|
|
@ -41,19 +41,19 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- At least one "structures" JAR must also be included -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
|
@ -63,14 +63,14 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- This dependency is used for the "FHIR Tester" web app overlay -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
database (e.g. Postgres). Consult the Hibernate documentation to see a list of
|
||||
available dialects.
|
||||
-->
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,22 +18,22 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
</bean>
|
||||
-->
|
||||
|
||||
<bean depends-on="dbServer" id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean depends-on="dbServer" id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<value>home , DSTU1 , UHN/HAPI Server (DSTU1 FHIR) , http://fhirtest.uhn.ca/baseDstu1</value>
|
||||
<value>hidev , DSTU2 , Health Intersections (DSTU2 FHIR) , http://fhir-dev.healthintersections.com.au/open</value>
|
||||
<value>hi , DSTU1 , Health Intersections (DSTU1 FHIR) , http://fhir.healthintersections.com.au/open</value>
|
||||
<value>furored2 , DSTU1 , Spark - Furore (DSTU2 FHIR) , http://spark-dstu2.furore.com/fhir</value>
|
||||
<value>furored2 , DSTU2 , Spark - Furore (DSTU2 FHIR) , http://spark-dstu2.furore.com/fhir</value>
|
||||
<value>furore , DSTU1 , Spark - Furore (DSTU1 FHIR) , http://spark.furore.com/fhir</value>
|
||||
<value>blaze , DSTU1 , Blaze (Orion Health) , https://fhir.orionhealth.com/blaze/fhir</value>
|
||||
<value>oridashi , DSTU1 , Oridashi , http://demo.oridashi.com.au:8190</value>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<!-- <property name="url" value="jdbc:derby:directory:myUnitTestDB;create=true" /> -->
|
||||
</bean>
|
||||
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<property name="persistenceXmlLocation" value="classpath:fhir_jpatest_persistence.xml" />
|
||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||
|
@ -47,7 +47,7 @@
|
|||
</property>
|
||||
</bean>
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -189,7 +189,7 @@
|
|||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -147,6 +147,29 @@ public class GenericClientTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissing() throws Exception {
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[]{new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return (new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
|
||||
client.search().forResource("Patient").where(Patient.NAME.isMissing(true)).execute();
|
||||
assertEquals("http://example.com/fhir/Patient?name%3Amissing=true", capt.getValue().getRequestLine().getUri());
|
||||
|
||||
client.search().forResource("Patient").where(Patient.NAME.isMissing(false)).execute();
|
||||
assertEquals("http://example.com/fhir/Patient?name%3Amissing=false", capt.getValue().getRequestLine().getUri());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithStringAutoDetectsEncoding() throws Exception {
|
||||
|
|
|
@ -9,12 +9,14 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
|
@ -38,10 +40,13 @@ import ca.uhn.fhir.model.dstu.resource.Observation;
|
|||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
|
@ -233,6 +238,75 @@ public class SearchTest {
|
|||
assertEquals("IDAAA (identifier123)", bundle.getEntries().get(0).getTitle().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* See #164
|
||||
*/
|
||||
@Test
|
||||
public void testSearchByPostWithParamsInBodyAndUrl() throws Exception {
|
||||
HttpPost filePost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?name=Central");
|
||||
|
||||
// add parameters to the post method
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
parameters.add(new BasicNameValuePair("_id", "aaa"));
|
||||
|
||||
UrlEncodedFormEntity sendentity = new UrlEncodedFormEntity(parameters, "UTF-8");
|
||||
filePost.setEntity(sendentity);
|
||||
|
||||
HttpResponse status = ourClient.execute(filePost);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
|
||||
Patient p = bundle.getResources(Patient.class).get(0);
|
||||
assertEquals("idaaa", p.getName().get(0).getFamilyAsSingleString());
|
||||
assertEquals("nameCentral", p.getName().get(1).getFamilyAsSingleString());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #164
|
||||
*/
|
||||
@Test
|
||||
public void testSearchByPostWithInvalidPostUrl() throws Exception {
|
||||
HttpPost filePost = new HttpPost("http://localhost:" + ourPort + "/Patient?name=Central"); // should end with _search
|
||||
|
||||
// add parameters to the post method
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
parameters.add(new BasicNameValuePair("_id", "aaa"));
|
||||
|
||||
UrlEncodedFormEntity sendentity = new UrlEncodedFormEntity(parameters, "UTF-8");
|
||||
filePost.setEntity(sendentity);
|
||||
|
||||
HttpResponse status = ourClient.execute(filePost);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<details value=\"Incorrect Content-Type header value of "application/x-www-form-urlencoded; charset=UTF-8" was provided in the request. A FHIR Content-Type is required for "CREATE" operation\"/>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* See #164
|
||||
*/
|
||||
@Test
|
||||
public void testSearchByPostWithMissingContentType() throws Exception {
|
||||
HttpPost filePost = new HttpPost("http://localhost:" + ourPort + "/Patient?name=Central"); // should end with _search
|
||||
|
||||
HttpEntity sendentity = new ByteArrayEntity(new byte[] {1,2,3,4} );
|
||||
filePost.setEntity(sendentity);
|
||||
|
||||
HttpResponse status = ourClient.execute(filePost);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<details value=\"No Content-Type header was provided in the request. This is required for "CREATE" operation\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCompartment() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/fooCompartment");
|
||||
|
@ -354,6 +428,14 @@ public class SearchTest {
|
|||
*/
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
/**
|
||||
* Only needed for #164
|
||||
*/
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam Patient thePatient) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Search(compartmentName = "fooCompartment")
|
||||
public List<Patient> compartment(@IdParam IdDt theId) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
@ -383,7 +465,7 @@ public class SearchTest {
|
|||
|
||||
|
||||
@Search
|
||||
public List<Patient> findPatient(@RequiredParam(name = "_id") StringParam theParam) {
|
||||
public List<Patient> findPatient(@RequiredParam(name = "_id") StringParam theParam, @OptionalParam(name="name") StringParam theName) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient patient = new Patient();
|
||||
|
@ -391,6 +473,9 @@ public class SearchTest {
|
|||
patient.addIdentifier("system", "identifier123");
|
||||
if (theParam != null) {
|
||||
patient.addName().addFamily("id" + theParam.getValue());
|
||||
if (theName != null) {
|
||||
patient.addName().addFamily("name" + theName.getValue());
|
||||
}
|
||||
}
|
||||
retVal.add(patient);
|
||||
return retVal;
|
||||
|
|
|
@ -33,6 +33,7 @@ import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
|||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
/**
|
||||
* HAPI/FHIR <b>Identifier</b> Datatype
|
||||
|
@ -402,5 +403,29 @@ public class IdentifierDt
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -9,10 +9,12 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -25,6 +27,7 @@ import static org.junit.Assert.fail;
|
|||
public class ResourceValidatorTest {
|
||||
|
||||
private static FhirContext ourCtx = new FhirContext();
|
||||
private static Locale ourDefaultLocale;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorTest.class);
|
||||
|
||||
@Test
|
||||
|
@ -45,10 +48,29 @@ public class ResourceValidatorTest {
|
|||
} catch (ValidationFailureException e) {
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
assertEquals(1, e.getOperationOutcome().getIssue().size());
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("Invalid content was found starting with element 'breed'"));
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("cvc-complex-type.2.4.a"));
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
/*
|
||||
* We cache the default locale, but temporarily set it to a random value during this test. This helps ensure that there are no
|
||||
* language specific dependencies in the test.
|
||||
*/
|
||||
ourDefaultLocale = Locale.getDefault();
|
||||
|
||||
Locale[] available = Locale.getAvailableLocales();
|
||||
Locale newLocale = available[(int)(Math.random() * available.length)];
|
||||
Locale.setDefault(newLocale);
|
||||
|
||||
ourLog.info("Tests are running in locale: " + newLocale.getDisplayName());
|
||||
}
|
||||
|
||||
public static void afterClass() {
|
||||
Locale.setDefault(ourDefaultLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #50
|
||||
*/
|
||||
|
@ -92,7 +114,7 @@ public class ResourceValidatorTest {
|
|||
} catch (ValidationFailureException e) {
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
assertEquals(1, e.getOperationOutcome().getIssue().size());
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("Inv-2: A system is required if a value is provided."));
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("Inv-2:"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +136,7 @@ public class ResourceValidatorTest {
|
|||
OperationOutcome operationOutcome = (OperationOutcome) validationResult.getOperationOutcome();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
|
||||
assertEquals(1, operationOutcome.getIssue().size());
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2: A system is required if a value is provided."));
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2:"));
|
||||
|
||||
p.getTelecomFirstRep().setSystem(ContactSystemEnum.EMAIL);
|
||||
validationResult = val.validateWithResult(p);
|
||||
|
@ -155,7 +177,7 @@ public class ResourceValidatorTest {
|
|||
OperationOutcome operationOutcome = (OperationOutcome) validationResult.getOperationOutcome();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
|
||||
assertEquals(1, operationOutcome.getIssue().size());
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2: A system is required if a value is provided."));
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2:"));
|
||||
}
|
||||
|
||||
private FhirValidator createFhirValidator() {
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
<logger name="org.eclipse" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="org.apache" additivity="false" level="debug">
|
||||
<logger name="org.apache" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="org.thymeleaf" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR Structures - DSTU2 (FHIR v0.4.0)</name>
|
||||
<name>HAPI FHIR Structures - DSTU2 (FHIR v0.5.0)</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -177,7 +177,7 @@
|
|||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -77,7 +77,7 @@ public class ClientServerValidationTestDstu2 {
|
|||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
// don't load the conformance until the first time the client is actually used
|
||||
|
@ -115,7 +115,7 @@ public class ClientServerValidationTestDstu2 {
|
|||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
|
||||
// don't load the conformance until the first time the client is actually used
|
||||
|
@ -143,7 +143,7 @@ public class ClientServerValidationTestDstu2 {
|
|||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
try {
|
||||
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
|
||||
fail();
|
||||
|
@ -173,19 +173,75 @@ public class ClientServerValidationTestDstu2 {
|
|||
myFirstResponse = false;
|
||||
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
|
||||
} else {
|
||||
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
|
||||
Patient resource = new Patient();
|
||||
resource.addName().addFamily().setValue("FAM");
|
||||
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(resource)), Charset.forName("UTF-8"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.ONCE);
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
client.registerInterceptor(new BasicAuthInterceptor("USER", "PASS"));
|
||||
client.read(new UriDt("http://foo/Patient/123"));
|
||||
Patient pt = (Patient) client.read(new UriDt("http://foo/Patient/123"));
|
||||
assertEquals("FAM", pt.getNameFirstRep().getFamilyAsSingleString());
|
||||
|
||||
Header auth = capt.getValue().getFirstHeader("Authorization");
|
||||
assertEquals(2, capt.getAllValues().size());
|
||||
|
||||
Header auth = capt.getAllValues().get(0).getFirstHeader("Authorization");
|
||||
assertNotNull(auth);
|
||||
assertEquals("Basic VVNFUjpQQVNT", auth.getValue());
|
||||
auth = capt.getAllValues().get(1).getFirstHeader("Authorization");
|
||||
assertNotNull(auth);
|
||||
assertEquals("Basic VVNFUjpQQVNT", auth.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForceConformanceCheck() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.5.0");
|
||||
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
||||
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<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
if (myFirstResponse) {
|
||||
myFirstResponse = false;
|
||||
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
|
||||
} else {
|
||||
Patient resource = new Patient();
|
||||
resource.addName().addFamily().setValue("FAM");
|
||||
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(resource)), Charset.forName("UTF-8"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
|
||||
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");
|
||||
client.registerInterceptor(new BasicAuthInterceptor("USER", "PASS"));
|
||||
|
||||
client.forceConformanceCheck();
|
||||
|
||||
assertEquals(1, capt.getAllValues().size());
|
||||
|
||||
Patient pt = (Patient) client.read(new UriDt("http://foo/Patient/123"));
|
||||
assertEquals("FAM", pt.getNameFirstRep().getFamilyAsSingleString());
|
||||
|
||||
assertEquals(2, capt.getAllValues().size());
|
||||
|
||||
Header auth = capt.getAllValues().get(0).getFirstHeader("Authorization");
|
||||
assertNotNull(auth);
|
||||
assertEquals("Basic VVNFUjpQQVNT", auth.getValue());
|
||||
auth = capt.getAllValues().get(1).getFirstHeader("Authorization");
|
||||
assertNotNull(auth);
|
||||
assertEquals("Basic VVNFUjpQQVNT", auth.getValue());
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
|
@ -35,7 +36,7 @@ import org.mockito.stubbing.Answer;
|
|||
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.Include;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -616,6 +617,64 @@ public class GenericClientDstu2Test {
|
|||
// assertEquals("PATIENT2", p2.getName().get(0).getFamily().get(0).getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithString() throws Exception {
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle req = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||
req.addEntry().setResource(new Patient());
|
||||
req.addEntry().setResource(new Observation());
|
||||
String reqStringJson = ourCtx.newJsonParser().encodeResourceToString(req);
|
||||
String reqStringXml = ourCtx.newXmlParser().encodeResourceToString(req);
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle resp = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||
resp.addEntry().getTransactionResponse().setLocation("Patient/1/_history/1");
|
||||
resp.addEntry().getTransactionResponse().setLocation("Patient/2/_history/2");
|
||||
final String respStringJson = ourCtx.newJsonParser().encodeResourceToString(resp);
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respStringJson), Charset.forName("UTF-8"));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
String response = client.transaction()
|
||||
.withBundle(reqStringJson)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/", capt.getValue().getURI().toString());
|
||||
assertEquals(respStringJson, response);
|
||||
String requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
|
||||
IOUtils.closeQuietly(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
|
||||
assertEquals(reqStringJson, requestString);
|
||||
assertEquals("application/json+fhir; charset=UTF-8", capt.getValue().getFirstHeader("Content-Type").getValue());
|
||||
|
||||
//@formatter:off
|
||||
response = client.transaction()
|
||||
.withBundle(reqStringJson)
|
||||
.encodedXml()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/?_format=xml", capt.getValue().getURI().toString());
|
||||
assertEquals(respStringJson, response);
|
||||
requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
|
||||
IOUtils.closeQuietly(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
|
||||
assertEquals(reqStringXml, requestString);
|
||||
assertEquals("application/xml+fhir; charset=UTF-8", capt.getValue().getFirstHeader("Content-Type").getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithTransactionResource() throws Exception {
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.core.StringContains;
|
||||
|
@ -65,7 +66,7 @@ public class ResourceValidatorDstu2Test {
|
|||
ourLog.info(resultString);
|
||||
|
||||
assertEquals(2, result.getOperationOutcome().getIssue().size());
|
||||
assertThat(resultString, StringContains.containsString("cvc-pattern-valid: Value '2000-15-31'"));
|
||||
assertThat(resultString, StringContains.containsString("'2000-15-31'"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -90,7 +91,7 @@ public class ResourceValidatorDstu2Test {
|
|||
} catch (ValidationFailureException e) {
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome());
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("if there's a duration, there needs to be"));
|
||||
assertThat(encoded, containsString("tim-1:"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ public class ResourceValidatorDstu2Test {
|
|||
OperationOutcome operationOutcome = (OperationOutcome) validationResult.getOperationOutcome();
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("if there's a duration, there needs to be"));
|
||||
assertThat(encoded, containsString("tim-1:"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -157,7 +158,7 @@ public class ResourceValidatorDstu2Test {
|
|||
} catch (ValidationFailureException e) {
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
assertEquals(1, e.getOperationOutcome().getIssue().size());
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("Invalid content was found starting with element 'breed'"));
|
||||
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetailsElement().getValue(), containsString("cvc-complex-type"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +180,7 @@ public class ResourceValidatorDstu2Test {
|
|||
OperationOutcome operationOutcome = (OperationOutcome) validationResult.getOperationOutcome();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
|
||||
assertEquals(1, operationOutcome.getIssue().size());
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails(), containsString("A system is required if a value is provided."));
|
||||
assertThat(operationOutcome.getIssueFirstRep().getDetails(), containsString("cpt-2:"));
|
||||
|
||||
p.getTelecomFirstRep().setSystem(ContactPointSystemEnum.EMAIL);
|
||||
validationResult = val.validateWithResult(p);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>0.9-SNAPSHOT</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>0.9-SNAPSHOT</version>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
|
@ -38,7 +38,7 @@
|
|||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>${servlet_api_version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -27,22 +27,22 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<!--<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
|
|
|
@ -127,7 +127,8 @@
|
|||
$('#server-history-datetime').datetimepicker({
|
||||
sideBySide: true,
|
||||
use24hours: true,
|
||||
showToday: true
|
||||
showToday: true,
|
||||
keepInvalid: true
|
||||
});
|
||||
});
|
||||
$('#server-history-btn').click(
|
||||
|
|
|
@ -326,7 +326,8 @@
|
|||
$('#resource-history-datetime').datetimepicker({
|
||||
sideBySide: true,
|
||||
use24hours: true,
|
||||
showToday: true
|
||||
showToday: true,
|
||||
keepInvalid: true
|
||||
});
|
||||
});
|
||||
$('#resource-history-btn').click(
|
||||
|
|
|
@ -145,6 +145,7 @@ PRE.resultBodyPre {
|
|||
background-color: transparent;
|
||||
overflow: visible;
|
||||
/*white-space: normal;*/
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
database (e.g. Postgres). Consult the Hibernate documentation to see a list of
|
||||
available dialects.
|
||||
-->
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<!--
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="myEntityManagerFactory" />
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="myTxManager" />
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
database (e.g. Postgres). Consult the Hibernate documentation to see a list of
|
||||
available dialects.
|
||||
-->
|
||||
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSource" />
|
||||
<!--
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<!--
|
||||
Because Tinder is a part of the HAPI FHIR build process (it generates
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>custom-structs</id>
|
||||
|
@ -104,7 +104,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
|
8
pom.xml
8
pom.xml
|
@ -12,9 +12,9 @@
|
|||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<name>HAPI-FHIR</name>
|
||||
<url>http://hl7api.sourceforge.net/hapi-fhir/</url>
|
||||
<url>http://jamesagnew.github.io/hapi-fhir/</url>
|
||||
|
||||
<organization>
|
||||
<name>University Health Network</name>
|
||||
|
@ -48,6 +48,10 @@
|
|||
</dependencies>
|
||||
|
||||
<prerequisites>
|
||||
<!--
|
||||
TODO: the version number here should probably be
|
||||
either 3.2 or 3.3. Check and fix
|
||||
-->
|
||||
<maven>3.0.1</maven>
|
||||
</prerequisites>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue