Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Thomas Andersen 2015-10-04 21:07:46 +02:00
commit e040ef3f43
85 changed files with 6920 additions and 1102 deletions

View File

@ -65,7 +65,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>

View File

@ -6,7 +6,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<classpathentry kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
@ -17,7 +17,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<classpathentry kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>

View File

@ -15,26 +15,6 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (1).launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>

View File

@ -37,25 +37,20 @@ public class BoundCodeDt<T extends Enum<?>> extends CodeDt {
public BoundCodeDt() {
// nothing
}
public BoundCodeDt(IValueSetEnumBinder<T> theBinder) {
Validate.notNull(theBinder, "theBinder must not be null");
myBinder = theBinder;
}
public BoundCodeDt(IValueSetEnumBinder<T> theBinder, T theValue) {
Validate.notNull(theBinder, "theBinder must not be null");
myBinder = theBinder;
setValueAsEnum(theValue);
}
public void setValueAsEnum(T theValue) {
Validate.notNull(myBinder, "This object does not have a binder. Constructor BoundCodeDt() should not be called!");
if (theValue==null) {
setValue(null);
} else {
setValue(myBinder.toCodeString(theValue));
}
public IValueSetEnumBinder<T> getBinder() {
return myBinder;
}
public T getValueAsEnum() {
@ -66,4 +61,13 @@ public class BoundCodeDt<T extends Enum<?>> extends CodeDt {
}
return retVal;
}
public void setValueAsEnum(T theValue) {
Validate.notNull(myBinder, "This object does not have a binder. Constructor BoundCodeDt() should not be called!");
if (theValue==null) {
setValue(null);
} else {
setValue(myBinder.toCodeString(theValue));
}
}
}

View File

@ -50,11 +50,6 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
// nothing
}
@Override
public boolean isEmpty() {
return super.isBaseEmpty() && (getValue() == null || getValue().isEmpty());
}
/**
* Constructor which accepts a string code
*
@ -65,27 +60,25 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
setValueAsString(theTextDiv);
}
/**
* Accepts a textual DIV and parses it into XHTML events which are stored internally.
* <p>
* <b>Formatting note:</b> The text will be trimmed {@link String#trim()}. If the text does not start with an HTML tag (generally this would be a div tag), a div tag will be automatically placed
* surrounding the text.
* </p>
* <p>
* Also note that if the parsed text contains any entities (&amp;foo;) which are not a part of the entities defined in core XML (e.g. &amp;sect; which
* is valid in XHTML 1.0 but not in XML 1.0) they will be parsed and converted to their equivalent unicode character.
* </p>
*/
@Override
public void setValueAsString(String theValue) throws DataFormatException {
if (theValue == null || theValue.isEmpty()) {
super.setValueAsString(null);
} else {
String value = theValue.trim();
if (value.charAt(0) != '<') {
value = "<div>" + value + "</div>";
protected String encode(List<XMLEvent> theValue) {
try {
StringWriter w = new StringWriter();
XMLEventWriter ew = XmlUtil.createXmlFragmentWriter(w);
for (XMLEvent next : getValue()) {
if (next.isCharacters()) {
ew.add(next);
} else {
ew.add(next);
}
}
super.setValueAsString(value);
ew.close();
return w.toString();
} catch (XMLStreamException e) {
throw new DataFormatException("Problem with the contained XML events", e);
} catch (FactoryConfigurationError e) {
throw new ConfigurationException(e);
}
}
@ -93,6 +86,11 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
return getValue() != null && getValue().size() > 0;
}
@Override
public boolean isEmpty() {
return super.isBaseEmpty() && (getValue() == null || getValue().isEmpty());
}
@Override
protected List<XMLEvent> parse(String theValue) {
String val = theValue.trim();
@ -128,24 +126,27 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
}
}
/**
* Accepts a textual DIV and parses it into XHTML events which are stored internally.
* <p>
* <b>Formatting note:</b> The text will be trimmed {@link String#trim()}. If the text does not start with an HTML tag (generally this would be a div tag), a div tag will be automatically placed
* surrounding the text.
* </p>
* <p>
* Also note that if the parsed text contains any entities (&amp;foo;) which are not a part of the entities defined in core XML (e.g. &amp;sect; which is valid in XHTML 1.0 but not in XML 1.0) they
* will be parsed and converted to their equivalent unicode character.
* </p>
*/
@Override
protected String encode(List<XMLEvent> theValue) {
try {
StringWriter w = new StringWriter();
XMLEventWriter ew = XmlUtil.createXmlWriter(w);
for (XMLEvent next : getValue()) {
if (next.isCharacters()) {
ew.add(next);
} else {
ew.add(next);
}
public void setValueAsString(String theValue) throws DataFormatException {
if (theValue == null || theValue.isEmpty()) {
super.setValueAsString(null);
} else {
String value = theValue.trim();
if (value.charAt(0) != '<') {
value = "<div>" + value + "</div>";
}
ew.close();
return w.toString();
} catch (XMLStreamException e) {
throw new DataFormatException("Problem with the contained XML events", e);
} catch (FactoryConfigurationError e) {
throw new ConfigurationException(e);
super.setValueAsString(value);
}
}

View File

@ -42,6 +42,7 @@ import org.apache.http.client.methods.HttpRequestBase;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseMetaType;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -100,6 +101,7 @@ import ca.uhn.fhir.rest.gclient.IOperation;
import ca.uhn.fhir.rest.gclient.IOperationUnnamed;
import ca.uhn.fhir.rest.gclient.IOperationUntyped;
import ca.uhn.fhir.rest.gclient.IOperationUntypedWithInput;
import ca.uhn.fhir.rest.gclient.IOperationUntypedWithInputAndPartialOutput;
import ca.uhn.fhir.rest.gclient.IParam;
import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.gclient.IRead;
@ -229,7 +231,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
return delete(theType, new IdDt(theId));
}
private <T extends IBaseResource> T doReadOrVRead(final Class<T> theType, IIdType theId, boolean theVRead, ICallable<T> theNotModifiedHandler, String theIfVersionMatches, Boolean thePrettyPrint, SummaryEnum theSummary, EncodingEnum theEncoding, Set<String> theSubsetElements) {
private <T extends IBaseResource> T doReadOrVRead(final Class<T> theType, IIdType theId, boolean theVRead, ICallable<T> theNotModifiedHandler, String theIfVersionMatches, Boolean thePrettyPrint,
SummaryEnum theSummary, EncodingEnum theEncoding, Set<String> theSubsetElements) {
String resName = toResourceName(theType);
IIdType id = theId;
if (!id.hasBaseUrl()) {
@ -906,6 +909,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
myCriterionList.add((ICriterionInternal) theCriterion);
return this;
}
@Override
public IDeleteWithQuery resourceConditionalByType(Class<? extends IBaseResource> theResourceType) {
Validate.notNull(theResourceType, "theResourceType can not be null");
myCriterionList = new CriterionList();
myResourceType = myContext.getResourceDefinition(theResourceType).getName();
return this;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@ -1353,13 +1364,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@SuppressWarnings("rawtypes")
private class OperationInternal extends BaseClientExecutable implements IOperation, IOperationUnnamed, IOperationUntyped, IOperationUntypedWithInput {
private class OperationInternal extends BaseClientExecutable implements IOperation, IOperationUnnamed, IOperationUntyped, IOperationUntypedWithInput, IOperationUntypedWithInputAndPartialOutput {
private IIdType myId;
private String myOperationName;
private IBaseParameters myParameters;
private Class<? extends IBaseResource> myType;
private boolean myUseHttpGet;
private RuntimeResourceDefinition myParametersDef;
@SuppressWarnings("unchecked")
@Override
@ -1455,6 +1467,51 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
@SuppressWarnings("unchecked")
@Override
public <T extends IBaseParameters> IOperationUntypedWithInputAndPartialOutput<T> withParameter(Class<T> theParameterType, String theName, IBase theValue) {
Validate.notNull(theParameterType, "theParameterType must not be null");
Validate.notEmpty(theName, "theName must not be null");
Validate.notNull(theValue, "theValue must not be null");
myParametersDef = myContext.getResourceDefinition(theParameterType);
myParameters = (IBaseParameters) myParametersDef.newInstance();
addParam(theName, theValue);
return this;
}
@SuppressWarnings("unchecked")
private void addParam(String theName, IBase theValue) {
BaseRuntimeChildDefinition parameterChild = myParametersDef.getChildByName("parameter");
BaseRuntimeElementCompositeDefinition<?> parameterElem = (BaseRuntimeElementCompositeDefinition<?>) parameterChild.getChildByName("parameter");
IBase parameter = parameterElem.newInstance();
parameterChild.getMutator().addValue(myParameters, parameter);
IPrimitiveType<String> name = (IPrimitiveType<String>) myContext.getElementDefinition("string").newInstance();
name.setValue(theName);
parameterElem.getChildByName("name").getMutator().setValue(parameter, name);
if (theValue instanceof IBaseDatatype) {
String childElementName = "value" + StringUtils.capitalize(myContext.getElementDefinition(theValue.getClass()).getName());
parameterElem.getChildByName(childElementName).getMutator().setValue(parameter, theValue);
} else if (theValue instanceof IBaseResource) {
parameterElem.getChildByName("resource").getMutator().setValue(parameter, theValue);
} else {
throw new IllegalArgumentException("Don't know how to handle parameter of type " + theValue.getClass());
}
}
@Override
public IOperationUntypedWithInputAndPartialOutput andParameter(String theName, IBase theValue) {
Validate.notEmpty(theName, "theName must not be null");
Validate.notNull(theValue, "theValue must not be null");
addParam(theName, theValue);
return this;
}
}
private final class OperationOutcomeResponseHandler implements IClientResponseHandler<BaseOperationOutcome> {
@ -1506,7 +1563,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private RuntimeResourceDefinition myType;
@Override
public Object execute() {//AAA
public Object execute() {// AAA
if (myId.hasVersionIdPart()) {
return doReadOrVRead(myType.getImplementingClass(), myId, true, myNotModifiedHandler, myIfVersionMatches, myPrettyPrint, mySummaryMode, myParamEncoding, getSubsetElements());
} else {
@ -1693,7 +1750,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
BaseRuntimeElementCompositeDefinition<?> textElement = (BaseRuntimeElementCompositeDefinition<?>) textChild.getChildByName("text");
IBase textInstance = textElement.newInstance();
textChild.getMutator().addValue(instance, textInstance);
BaseRuntimeChildDefinition divChild = textElement.getChildByName("div");
BaseRuntimeElementDefinition<?> divElement = divChild.getChildByName("div");
IPrimitiveType<?> divInstance = (IPrimitiveType<?>) divElement.newInstance();

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.rest.gclient;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.IResource;
@ -43,8 +44,15 @@ public interface IDelete {
IDeleteTyped resourceConditionalByUrl(String theSearchUrl);
/**
* Delete using a conditional/match URL. The query parameters will be added in the next part of the call chain.
* @since HAPI 0.9 / FHIR DSTU 2
*/
IDeleteWithQuery resourceConditionalByType(String theResourceType);
/**
* Delete using a conditional/match URL. The query parameters will be added in the next part of the call chain.
* @since HAPI 1.3
*/
IDeleteWithQuery resourceConditionalByType(Class<? extends IBaseResource> theResourceType);
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.gclient;
import org.hl7.fhir.instance.model.api.IBase;
/*
* #%L
* HAPI FHIR - Core Library
@ -40,4 +42,16 @@ public interface IOperationUntyped {
*/
<T extends IBaseParameters> IOperationUntypedWithInput<T> withNoParameters(Class<T> theOutputParameterType);
/**
* Use chained method calls to construct a Parameters input. This form is a convenience
* in order to allow simple method chaining to be used to build up a parameters
* resource for the input of an operation without needing to manually construct one.
*
* @param theParameterType The type to use for the output parameters (this should be set to
* <code>Parameters.class</code> drawn from the version of the FHIR structures you are using)
* @param theName The first parameter name
* @param theValue The first parameter value
*/
<T extends IBaseParameters> IOperationUntypedWithInputAndPartialOutput<T> withParameter(Class<T> theParameterType, String theName, IBase theValue);
}

View File

@ -0,0 +1,38 @@
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 org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseParameters;
public interface IOperationUntypedWithInputAndPartialOutput<T extends IBaseParameters> extends IOperationUntypedWithInput<T> {
/**
* Use chained method calls to construct a Parameters input. This form is a convenience
* in order to allow simple method chaining to be used to build up a parameters
* resource for the input of an operation without needing to manually construct one.
*
* @param theName The first parameter name
* @param theValue The first parameter value
*/
IOperationUntypedWithInputAndPartialOutput<T> andParameter(String theName, IBase theValue);
}

View File

@ -73,6 +73,10 @@ public abstract class BaseServerResponseException extends RuntimeException {
private String myResponseMimeType;
private int myStatusCode;
public static void main (String[] args) {
BaseServerResponseException.class.getName();
}
/**
* Constructor
*

View File

@ -43,11 +43,13 @@ import ca.uhn.fhir.util.OperationOutcomeUtil;
public class ExceptionHandlingInterceptor extends InterceptorAdapter {
public static final String PROCESSING = "processing";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionHandlingInterceptor.class);
private Class<?>[] myReturnStackTracesForExceptionTypes;
@Override
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse)
throws ServletException, IOException {
FhirContext ctx = theRequestDetails.getServer().getFhirContext();
@ -116,12 +118,20 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
ourLog.error("Failure during REST processing", theException);
populateDetails(ctx, theException, oo);
} else if (theException instanceof BaseServerResponseException) {
ourLog.warn("Failure during REST processing: {}", theException);
int statusCode = ((BaseServerResponseException) theException).getStatusCode();
// No stack traces for non-server internal errors
if (statusCode < 500) {
ourLog.warn("Failure during REST processing: {}", theException.toString());
} else {
ourLog.warn("Failure during REST processing: {}", theException);
}
BaseServerResponseException baseServerResponseException = (BaseServerResponseException) theException;
populateDetails(ctx, theException, oo);
if (baseServerResponseException.getAdditionalMessages() != null) {
for (String next : baseServerResponseException.getAdditionalMessages()) {
OperationOutcomeUtil.addIssue(ctx, oo, "error", next);
OperationOutcomeUtil.addIssue(ctx, oo, "error", next, null, PROCESSING);
}
}
} else {
@ -143,19 +153,18 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
for (Class<?> next : myReturnStackTracesForExceptionTypes) {
if (next.isAssignableFrom(theException.getClass())) {
String detailsValue = theException.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(theException);
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", detailsValue);
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", detailsValue, null, PROCESSING);
return;
}
}
}
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", theException.getMessage());
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", theException.getMessage(), null, PROCESSING);
}
/**
* If any server methods throw an exception which extends any of the given exception types, the exception stack trace
* will be returned to the user. This can be useful for helping to diagnose issues, but may not be desirable for
* production situations.
* If any server methods throw an exception which extends any of the given exception types, the exception stack trace will be returned to the user. This can be useful for helping to diagnose
* issues, but may not be desirable for production situations.
*
* @param theExceptionTypes
* The exception types for which to return the stack trace to the user.

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.server.interceptor;
import java.io.IOException;
/*
* #%L
* HAPI FHIR - Core Library
@ -24,6 +26,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -38,6 +41,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
/**
* Server interceptor which logs each request using a defined format
@ -67,8 +71,8 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
* </tr>
* <tr>
* <td>${requestHeader.XXXX}</td>
* <td>The value of the HTTP request header named XXXX. For example, a substitution variable named
* "${requestHeader.x-forwarded-for} will yield the value of the first header named "x-forwarded-for", or "" if none.</td>
* <td>The value of the HTTP request header named XXXX. For example, a substitution variable named "${requestHeader.x-forwarded-for} will yield the value of the first header named "x-forwarded-for
* ", or "" if none.</td>
* </tr>
* <tr>
* <td>${requestParameters}</td>
@ -82,15 +86,52 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
* <td>${servletPath}</td>
* <td>The part of thre requesting URL that corresponds to the particular Servlet being called (see {@link HttpServletRequest#getServletPath()})</td>
* </tr>
* <tr>
* <td>${requestUrl}</td>
* <td>The complete URL of the request</td>
* </tr>
* <tr>
* <td>${requestVerb}</td>
* <td>The HTTP verb of the request</td>
* </tr>
* <tr>
* <td>${exceptionMessage}</td>
* <td>Applies only to an error message: The message from {@link Exception#getMessage()}</td>
* </tr>
* </table>
*/
public class LoggingInterceptor extends InterceptorAdapter {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LoggingInterceptor.class);
private String myErrorMessageFormat = "ERROR - ${idOrResourceName}";
private boolean myLogExceptions;
private Logger myLogger = ourLog;
private String myMessageFormat = "${operationType} - ${idOrResourceName}";
/**
* Get the log message format to be used when logging exceptions
*/
public String getErrorMessageFormat() {
return myErrorMessageFormat;
}
@Override
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
throws ServletException, IOException {
if (myLogExceptions) {
// Perform any string substitutions from the message format
StrLookup<?> lookup = new MyLookup(theServletRequest, theException, theRequestDetails);
StrSubstitutor subs = new StrSubstitutor(lookup, "${", "}", '\\');
// Actuall log the line
String line = subs.replace(myErrorMessageFormat);
myLogger.info(line);
}
return true;
}
@Override
public boolean incomingRequestPostProcessed(final RequestDetails theRequestDetails, final HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
@ -105,6 +146,28 @@ public class LoggingInterceptor extends InterceptorAdapter {
return true;
}
/**
* Should exceptions be logged by this logger
*/
public boolean isLogExceptions() {
return myLogExceptions;
}
/**
* Set the log message format to be used when logging exceptions
*/
public void setErrorMessageFormat(String theErrorMessageFormat) {
Validate.notBlank(theErrorMessageFormat, "Message format can not be null/empty");
myErrorMessageFormat = theErrorMessageFormat;
}
/**
* Should exceptions be logged by this logger
*/
public void setLogExceptions(boolean theLogExceptions) {
myLogExceptions = theLogExceptions;
}
public void setLogger(Logger theLogger) {
Validate.notNull(theLogger, "Logger can not be null");
myLogger = theLogger;
@ -125,12 +188,20 @@ public class LoggingInterceptor extends InterceptorAdapter {
}
private static final class MyLookup extends StrLookup<String> {
private final Throwable myException;
private final HttpServletRequest myRequest;
private final RequestDetails myRequestDetails;
private MyLookup(HttpServletRequest theRequest, RequestDetails theRequestDetails) {
myRequest = theRequest;
myRequestDetails = theRequestDetails;
myException = null;
}
public MyLookup(HttpServletRequest theServletRequest, BaseServerResponseException theException, RequestDetails theRequestDetails) {
myException = theException;
myRequestDetails = theRequestDetails;
myRequest = theServletRequest;
}
@Override
@ -204,6 +275,12 @@ public class LoggingInterceptor extends InterceptorAdapter {
} else {
return "";
}
} else if (theKey.equals("exceptionMessage")) {
return myException != null ? myException.getMessage() : null;
} else if (theKey.equals("requestUrl")) {
return myRequest.getRequestURL().toString();
} else if (theKey.equals("requestVerb")) {
return myRequest.getMethod();
}
return "!VAL!";

View File

@ -42,22 +42,23 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
*/
public class OperationOutcomeUtil {
/**
* Add an issue to an OperationOutcome
*
* @param theCtx
* The fhir context
* @param theOperationOutcome
* The OO resource to add to
* @param theSeverity
* The severity (e.g. "error")
* @param theDetails
* The details string
*/
public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails) {
IBase issue = createIssue(theCtx, theOperationOutcome);
populateDetails(theCtx, issue, theSeverity, theDetails, null);
}
// /**
// * Add an issue to an OperationOutcome
// *
// * @param theCtx
// * The fhir context
// * @param theOperationOutcome
// * The OO resource to add to
// * @param theSeverity
// * The severity (e.g. "error")
// * @param theDetails
// * The details string
// * @param theCode
// */
// public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails, String theCode) {
// IBase issue = createIssue(theCtx, theOperationOutcome);
// populateDetails(theCtx, issue, theSeverity, theDetails, null, theCode);
// }
/**
* Add an issue to an OperationOutcome
@ -70,10 +71,11 @@ public class OperationOutcomeUtil {
* The severity (e.g. "error")
* @param theDetails
* The details string
* @param theCode
*/
public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails, String theLocation) {
public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails, String theLocation, String theCode) {
IBase issue = createIssue(theCtx, theOperationOutcome);
populateDetails(theCtx, issue, theSeverity, theDetails, theLocation);
populateDetails(theCtx, issue, theSeverity, theDetails, theLocation, theCode);
}
private static IBase createIssue(FhirContext theCtx, IBaseResource theOutcome) {
@ -145,11 +147,16 @@ public class OperationOutcomeUtil {
}
}
private static void populateDetails(FhirContext theCtx, IBase theIssue, String theSeverity, String theDetails, String theLocation) {
private static void populateDetails(FhirContext theCtx, IBase theIssue, String theSeverity, String theDetails, String theLocation, String theCode) {
BaseRuntimeElementCompositeDefinition<?> issueElement = (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(theIssue.getClass());
BaseRuntimeChildDefinition detailsChild;
if (theCtx.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
detailsChild = issueElement.getChildByName("diagnostics");
BaseRuntimeChildDefinition codeChild = issueElement.getChildByName("code");
IPrimitiveType<?> codeElem = (IPrimitiveType<?>) codeChild.getChildByName("code").newInstance(codeChild.getInstanceConstructorArguments());
codeElem.setValueAsString(theCode);
codeChild.getMutator().addValue(theIssue, codeElem);
} else {
detailsChild = issueElement.getChildByName("details");
}

View File

@ -173,17 +173,22 @@ public class UrlUtil {
*/
//@formatter:on
public static UrlParts parseUrl(String theUrl) {
String url = theUrl;
if (url.matches("\\/[a-zA-Z]+\\?.*")) {
url = url.substring(1);
}
UrlParts retVal = new UrlParts();
int nextStart = 0;
boolean nextIsHistory = false;
for (int idx = 0; idx < theUrl.length(); idx++) {
char nextChar = theUrl.charAt(idx);
boolean atEnd = (idx + 1) == theUrl.length();
for (int idx = 0; idx < url.length(); idx++) {
char nextChar = url.charAt(idx);
boolean atEnd = (idx + 1) == url.length();
if (nextChar == '?' || nextChar == '/' || atEnd) {
int endIdx = atEnd ? idx + 1 : idx;
String nextSubstring = theUrl.substring(nextStart, endIdx);
String nextSubstring = url.substring(nextStart, endIdx);
if (retVal.getResourceType() == null) {
retVal.setResourceType(nextSubstring);
} else if (retVal.getResourceId() == null) {
@ -194,12 +199,12 @@ public class UrlUtil {
if (nextSubstring.equals(Constants.URL_TOKEN_HISTORY)) {
nextIsHistory = true;
} else {
throw new InvalidRequestException("Invalid FHIR resource URL: " + theUrl);
throw new InvalidRequestException("Invalid FHIR resource URL: " + url);
}
}
if (nextChar == '?') {
if (theUrl.length() > idx + 1) {
retVal.setParams(theUrl.substring(idx + 1, theUrl.length()));
if (url.length() > idx + 1) {
retVal.setParams(url.substring(idx + 1, url.length()));
}
break;
}

View File

@ -68,6 +68,7 @@ public class XmlUtil {
private static volatile XMLInputFactory ourInputFactory;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class);
private static volatile XMLOutputFactory ourOutputFactory;
private static XMLOutputFactory ourFragmentOutputFactory;
private static final Map<String, Integer> VALID_ENTITY_NAMES;
private static final ExtendedEntityReplacingXmlResolver XML_RESOLVER = new ExtendedEntityReplacingXmlResolver();
@ -1539,6 +1540,12 @@ public class XmlUtil {
return retVal;
}
public static XMLEventWriter createXmlFragmentWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateFragmentOutputFactory();
XMLEventWriter retVal = outputFactory.createXMLEventWriter(theWriter);
return retVal;
}
public static XMLEventWriter createXmlWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateOutputFactory();
XMLEventWriter retVal = outputFactory.createXMLEventWriter(theWriter);
@ -1589,40 +1596,55 @@ public class XmlUtil {
return ourInputFactory;
}
private static XMLOutputFactory getOrCreateFragmentOutputFactory() throws FactoryConfigurationError {
XMLOutputFactory retVal = ourFragmentOutputFactory;
if (retVal == null) {
retVal = createOutputFactory();
retVal.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
ourFragmentOutputFactory = retVal;
return retVal;
}
return retVal;
}
private static XMLOutputFactory getOrCreateOutputFactory() throws FactoryConfigurationError {
if (ourOutputFactory == null) {
try {
// Detect if we're running with the Android lib, and force repackaged Woodstox to be used
Class.forName("ca.uhn.fhir.repackage.javax.xml.stream.XMLOutputFactory");
System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory");
} catch (ClassNotFoundException e) {
// ok
}
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(outputFactory.getClass());
}
/*
* Note that these properties are Woodstox specific and they cause a crash in environments where SJSXP is
* being used (e.g. glassfish) so we don't set them there.
*/
try {
Class.forName("com.ctc.wstx.stax.WstxOutputFactory");
if (outputFactory instanceof WstxOutputFactory) {
outputFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new MyEscaper());
}
} catch (ClassNotFoundException e) {
ourLog.debug("WstxOutputFactory (Woodstox) not found on classpath");
}
ourOutputFactory = outputFactory;
ourOutputFactory = createOutputFactory();
}
return ourOutputFactory;
}
private static XMLOutputFactory createOutputFactory() throws FactoryConfigurationError {
try {
// Detect if we're running with the Android lib, and force repackaged Woodstox to be used
Class.forName("ca.uhn.fhir.repackage.javax.xml.stream.XMLOutputFactory");
System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory");
} catch (ClassNotFoundException e) {
// ok
}
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(outputFactory.getClass());
}
/*
* Note that these properties are Woodstox specific and they cause a crash in environments where SJSXP is
* being used (e.g. glassfish) so we don't set them there.
*/
try {
Class.forName("com.ctc.wstx.stax.WstxOutputFactory");
if (outputFactory instanceof WstxOutputFactory) {
outputFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new MyEscaper());
}
} catch (ClassNotFoundException e) {
ourLog.debug("WstxOutputFactory (Woodstox) not found on classpath");
}
return outputFactory;
}
private static URL getRootUrlForClass(Class<?> cls) {
ClassLoader classLoader = cls.getClassLoader();
String resource = cls.getName().replace('.', '/') + ".class";

View File

@ -28,6 +28,7 @@ import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
import ca.uhn.fhir.util.OperationOutcomeUtil;
/**
@ -107,7 +108,7 @@ public class ValidationResult {
location = null;
}
String severity = next.getSeverity() != null ? next.getSeverity().getCode() : null;
OperationOutcomeUtil.addIssue(myCtx, oo, severity, next.getMessage(), location);
OperationOutcomeUtil.addIssue(myCtx, oo, severity, next.getMessage(), location, ExceptionHandlingInterceptor.PROCESSING);
}
return oo;

View File

@ -47,6 +47,13 @@
<!-- Don't include in standard distribution -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-android</artifactId>
<version>1.3-SNAPSHOT</version>
<!-- Don't include in standard distribution -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
@ -100,6 +107,7 @@
<descriptor>${project.basedir}/src/assembly/hapi-fhir-standard-distribution.xml</descriptor>
<descriptor>${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml</descriptor>
<descriptor>${project.basedir}/src/assembly/hapi-fhir-android-distribution.xml</descriptor>
<descriptor>${project.basedir}/src/assembly/hapi-fhir-cli.xml</descriptor>
</descriptors>
</configuration>
</execution>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>android-distribution</id>
@ -15,9 +16,38 @@
<directory>${project.basedir}/../hapi-fhir-android/target/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>hapi-fhir-android-${project.version}*.jar</include>
<include>hapi-fhir-android-${project.version}.jar</include>
<include>hapi-fhir-android-${project.version}-dstu.jar</include>
<include>hapi-fhir-android-${project.version}-dstu2.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>false</unpack>
<scope>provided</scope>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>ca.uhn.hapi.fhir:hapi-fhir-android</include>
</includes>
<excludes>
<exclude>ca.uhn.hapi.fhir:hapi-fhir-base</exclude>
<exclude>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</exclude>
<exclude>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</exclude>
<exclude>ca.uhn.hapi.fhir:hapi-fhir-structures-hl7org-dstu2</exclude>
<exclude>ca.uhn.hapi.fhir:hapi-fhir-validation-resources-dstu2</exclude>
<exclude>org.glassfish:javax.json</exclude>
<exclude>org.codehaus.woodstox:woodstox-core-asl</exclude>
<exclude>javax.xml.stream:stax-api</exclude>
<exclude>org.codehaus.woodstox:stax2-api</exclude>
<exclude>org.glassfish:javax.json</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/test/java">
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="src" path="src/main/java">
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="target/generated-sources/tinder"/>
<classpathentry kind="src" path="target/generated-resources/tinder">
<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/classes" path="target/generated-sources/tinder"/>
<classpathentry kind="src" output="target/classes" path="target/generated-resources/tinder">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>

View File

@ -16,26 +16,6 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder (1).launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (2).launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>

View File

@ -174,8 +174,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
continue;
}
@ -193,7 +192,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
String[] nextPathsSplit = nextPathsUnsplit.split("\\|");
for (String nextPath : nextPathsSplit) {
nextPath = nextPath.trim();
List<Class<? extends IBaseResource>> allowedTypesInField = null;
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject == null) {
@ -219,7 +218,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
try {
resourceDefinition = getContext().getResourceDefinition(typeString);
} catch (DataFormatException e) {
throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextValue.getReference().getValue());
throw new InvalidRequestException(
"Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextValue.getReference().getValue());
}
Class<? extends IBaseResource> type = resourceDefinition.getImplementingClass();
@ -253,15 +253,16 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
String resName = targetResourceDef.getName();
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit);
}
if (!typeString.equals(target.getResourceType())) {
throw new UnprocessableEntityException("Resource contains reference to " + nextValue.getReference().getValue() + " but resource with ID " + nextValue.getReference().getIdPart() + " is actually of type " + target.getResourceType());
throw new UnprocessableEntityException("Resource contains reference to " + nextValue.getReference().getValue() + " but resource with ID " + nextValue.getReference().getIdPart()
+ " is actually of type " + target.getResourceType());
}
/*
* Is the target type an allowable type of resource for the path where it is referenced?
*/
if (allowedTypesInField == null) {
BaseRuntimeChildDefinition childDef = getContext().newTerser().getDefinition(theResource.getClass(), nextPath);
if (childDef instanceof RuntimeChildResourceDefinition) {
@ -272,19 +273,19 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
allowedTypesInField.add(IBaseResource.class);
}
}
boolean acceptableLink = false;
for(Class<? extends IBaseResource> next : allowedTypesInField) {
for (Class<? extends IBaseResource> next : allowedTypesInField) {
if (next.isAssignableFrom(targetResourceDef.getImplementingClass())) {
acceptableLink = true;
break;
}
}
if (!acceptableLink) {
throw new UnprocessableEntityException("Invalid reference found at path '" + nextPath + "'. Resource type '" + targetResourceDef.getName() + "' is not valid for this path");
}
nextEntity = new ResourceLink(nextPath, theEntity, target);
} else {
if (!multiType) {
@ -683,11 +684,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
/**
* This method is called when an update to an existing resource detects that the resource supplied for update is
* missing a tag/profile/security label that the currently persisted resource holds.
* This method is called when an update to an existing resource detects that the resource supplied for update is missing a tag/profile/security label that the currently persisted resource holds.
* <p>
* The default implementation removes any profile declarations, but leaves tags and security labels in place.
* Subclasses may choose to override and change this behaviour.
* The default implementation removes any profile declarations, but leaves tags and security labels in place. Subclasses may choose to override and change this behaviour.
* </p>
*
* @param theEntity
@ -695,8 +694,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
* @param theTag
* The tag
* @return Retturns <code>true</code> if the tag should be removed
* @see <a href="http://hl7.org/fhir/2015Sep/resource.html#1.11.3.7">Updates to Tags, Profiles, and Security
* Labels</a> for a description of the logic that the default behaviour folows.
* @see <a href="http://hl7.org/fhir/2015Sep/resource.html#1.11.3.7">Updates to Tags, Profiles, and Security Labels</a> for a description of the logic that the default behaviour folows.
*/
protected boolean shouldDroppedTagBeRemovedOnUpdate(ResourceTable theEntity, ResourceTag theTag) {
if (theTag.getTag().getTagType() == TagTypeEnum.PROFILE) {
@ -709,6 +707,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
if (paramMap.isEmpty()) {
throw new InvalidRequestException("Invalid match URL[" + theMatchUrl + "] - URL has no search parameters");
}
IFhirResourceDao<R> dao = getDao(theResourceType);
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
@ -719,23 +721,28 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
public static SearchParameterMap translateMatchUrl(String theMatchUrl, RuntimeResourceDefinition resourceDef) {
SearchParameterMap paramMap = new SearchParameterMap();
List<NameValuePair> parameters;
try {
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");
matchUrl = matchUrl.replace("=>=", "=%3E%3D");
matchUrl = matchUrl.replace("=<=", "=%3C%3D");
matchUrl = matchUrl.replace("=>", "=%3E");
matchUrl = matchUrl.replace("=<", "=%3C");
parameters = URLEncodedUtils.parse(new URI(matchUrl), "UTF-8");
} catch (URISyntaxException e) {
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
String matchUrl = theMatchUrl;
int questionMarkIndex = matchUrl.indexOf('?');
if (questionMarkIndex != -1) {
matchUrl = matchUrl.substring(questionMarkIndex + 1);
}
matchUrl = matchUrl.replace("|", "%7C");
matchUrl = matchUrl.replace("=>=", "=%3E%3D");
matchUrl = matchUrl.replace("=<=", "=%3C%3D");
matchUrl = matchUrl.replace("=>", "=%3E");
matchUrl = matchUrl.replace("=<", "=%3C");
if (matchUrl.contains(" ")) {
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - URL is invalid (must not contain spaces)");
}
parameters = URLEncodedUtils.parse((matchUrl), Constants.CHARSET_UTF8, '&');
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
for (NameValuePair next : parameters) {
if (isBlank(next.getValue())) {
continue;
}
String paramName = next.getName();
String qualifier = null;
for (int i = 0; i < paramMap.size(); i++) {
@ -779,11 +786,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
continue;
}
if (nextParamName.startsWith("_")) {
continue;
}
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
if (paramDef == null) {
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
@ -1030,8 +1037,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
} else if (theForHistoryOperation) {
/*
* If the create and update times match, this was when the resource was created
* so we should mark it as a POST. Otherwise, it's a PUT.
* If the create and update times match, this was when the resource was created so we should mark it as a POST. Otherwise, it's a PUT.
*/
Date published = theEntity.getPublished().getValue();
Date updated = theEntity.getUpdated().getValue();
@ -1041,7 +1047,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.put(res, BundleEntryTransactionMethodEnum.PUT);
}
}
res.setId(theEntity.getIdDt());
ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion()));
@ -1125,8 +1131,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
@SuppressWarnings("unchecked")
protected ResourceTable updateEntity(final IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, Date theUpdateTime) {
protected ResourceTable updateEntity(final IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime) {
/*
* This should be the very first thing..
*/
@ -1134,14 +1141,15 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
validateResourceForStorage((T) theResource, theEntity);
String resourceType = myContext.getResourceDefinition(theResource).getName();
if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) {
throw new UnprocessableEntityException("Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
throw new UnprocessableEntityException(
"Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
}
}
if (theEntity.getPublished() == null) {
theEntity.setPublished(theUpdateTime);
}
if (theUpdateHistory) {
final ResourceHistoryTable historyEntry = theEntity.toHistory();
myEntityManager.persist(historyEntry);
@ -1238,7 +1246,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
theEntity.setResourceLinks(links);
theEntity.setHasLinks(links.isEmpty() == false);
theEntity.setIndexStatus(INDEX_STATUS_INDEXED);
} else {
populateResourceIntoEntity(theResource, theEntity);
@ -1261,7 +1269,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
} else {
theEntity = myEntityManager.merge(theEntity);
postUpdate(theEntity, (T) theResource);
}
@ -1354,37 +1362,37 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
/**
* Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the
* first time.
* Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the first time.
*
* @param theEntity
* The resource
* @param theResource The resource being persisted
* @param theResource
* The resource being persisted
*/
protected void postUpdate(ResourceTable theEntity, T theResource) {
// nothing
}
/**
* Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the
* first time.
* Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the first time.
*
* @param theEntity
* The resource
* @param theResource The resource being persisted
* @param theResource
* The resource being persisted
*/
protected void postPersist(ResourceTable theEntity, T theResource) {
// nothing
}
/**
* This method is invoked immediately before storing a new resource, or an update to an existing resource to allow
* the DAO to ensure that it is valid for persistence. By default, checks for the "subsetted" tag and rejects
* resources which have it. Subclasses should call the superclass implementation to preserve this check.
* This method is invoked immediately before storing a new resource, or an update to an existing resource to allow the DAO to ensure that it is valid for persistence. By default, checks for the
* "subsetted" tag and rejects resources which have it. Subclasses should call the superclass implementation to preserve this check.
*
* @param theResource
* The resource that is about to be persisted
* @param theEntityToSave TODO
* @param theEntityToSave
* TODO
*/
protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) {
IResource res = (IResource) theResource;

View File

@ -74,6 +74,7 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.entity.BaseTag;
@ -128,6 +129,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.FhirTerser;
@ -148,6 +150,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
@Autowired
private PlatformTransactionManager myPlatformTransactionManager;
@Autowired
private DaoConfig myDaoConfig;
private String myResourceName;
private Class<T> myResourceType;
private String mySecondaryPrimaryKeyParamName;
@ -1308,7 +1313,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
throw new InvalidRequestException("Trying to delete " + theId + " but this is not the current version");
}
validateOkToDeleteOrThrowPreconditionFailedException(entity);
validateOkToDeleteOrThrowResourceVersionConflictException(entity);
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType());
@ -1331,26 +1336,31 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
if (resource.isEmpty()) {
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "unableToDeleteNotFound", theUrl));
} else if (resource.size() > 1) {
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resource.size()));
if (myDaoConfig.isAllowMultipleDelete() == false) {
throw new PreconditionFailedException(getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resource.size()));
}
}
Long pid = resource.iterator().next();
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
validateOkToDeleteOrThrowPreconditionFailedException(entity);
// Notify interceptors
IdDt idToDelete = entity.getIdDt();
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType());
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
// Perform delete
Date updateTime = new Date();
ResourceTable savedEntity = updateEntity(null, entity, true, updateTime, updateTime);
notifyWriteCompleted();
ourLog.info("Processed delete on {} in {}ms", theUrl, w.getMillisAndRestart());
return toMethodOutcome(savedEntity, null);
for (Long pid : resource) {
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
validateOkToDeleteOrThrowResourceVersionConflictException(entity);
// Notify interceptors
IdDt idToDelete = entity.getIdDt();
ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType());
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
// Perform delete
Date updateTime = new Date();
updateEntity(null, entity, true, updateTime, updateTime);
notifyWriteCompleted();
}
ourLog.info("Processed delete on {} (matched {} resource(s)) in {}ms", new Object[] {theUrl, resource.size(), w.getMillisAndRestart()});
return new DaoMethodOutcome();
}
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing, Date theUpdateTime) {
@ -1615,7 +1625,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
/**
* THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet())
*/
private HashSet<Long> loadReverseIncludes(Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode) {
private HashSet<Long> loadReverseIncludes(Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, EverythingModeEnum theEverythingModeEnum) {
if (theMatches.size() == 0) {
return new HashSet<Long>();
}
@ -1632,6 +1642,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
boolean addedSomeThisRound;
do {
HashSet<Long> pidsToInclude = new HashSet<Long>();
Set<Long> nextRoundOmit = new HashSet<Long>();
for (Iterator<Include> iter = includes.iterator(); iter.hasNext();) {
Include nextInclude = iter.next();
@ -1648,6 +1659,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
List<ResourceLink> results = q.getResultList();
for (ResourceLink resourceLink : results) {
if (theReverseMode) {
if (theEverythingModeEnum == EverythingModeEnum.ENCOUNTER) {
if (resourceLink.getSourcePath().equals("Encounter.subject") || resourceLink.getSourcePath().equals("Encounter.patient")) {
nextRoundOmit.add(resourceLink.getSourceResourcePid());
}
}
pidsToInclude.add(resourceLink.getSourceResourcePid());
} else {
pidsToInclude.add(resourceLink.getTargetResourcePid());
@ -1702,6 +1718,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
theMatches.add(next);
}
}
pidsToInclude.removeAll(nextRoundOmit);
addedSomeThisRound = allAdded.addAll(pidsToInclude);
nextRoundMatches = pidsToInclude;
} while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound);
@ -2024,10 +2043,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
}
// Load _include and _revinclude before filter and sort in everything mode
if (theParams.isEverythingMode() == true) {
if (theParams.getEverythingMode() != null) {
if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) {
loadPids.addAll(loadReverseIncludes(loadPids, theParams.getRevIncludes(), true));
loadPids.addAll(loadReverseIncludes(loadPids, theParams.getIncludes(), false));
loadPids.addAll(loadReverseIncludes(loadPids, theParams.getRevIncludes(), true, theParams.getEverythingMode()));
loadPids.addAll(loadReverseIncludes(loadPids, theParams.getIncludes(), false, theParams.getEverythingMode()));
}
}
@ -2066,9 +2085,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
// Load _revinclude resources
final Set<Long> revIncludedPids;
if (theParams.isEverythingMode() == false) {
if (theParams.getEverythingMode() == null) {
if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) {
revIncludedPids = loadReverseIncludes(pids, theParams.getRevIncludes(), true);
revIncludedPids = loadReverseIncludes(pids, theParams.getRevIncludes(), true, null);
} else {
revIncludedPids = new HashSet<Long>();
}
@ -2095,9 +2114,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
List<Long> pidsSubList = pids.subList(theFromIndex, theToIndex);
// Load includes
if (!theParams.isEverythingMode()) {
if (theParams.getEverythingMode()==null) {
pidsSubList = new ArrayList<Long>(pidsSubList);
revIncludedPids.addAll(loadReverseIncludes(pidsSubList, theParams.getIncludes(), false));
revIncludedPids.addAll(loadReverseIncludes(pidsSubList, theParams.getIncludes(), false, null));
}
// Execute the query and make sure we return distinct results
@ -2502,7 +2521,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
}
}
protected void validateOkToDeleteOrThrowPreconditionFailedException(ResourceTable theEntity) {
protected void validateOkToDeleteOrThrowResourceVersionConflictException(ResourceTable theEntity) {
TypedQuery<ResourceLink> query = myEntityManager.createQuery("SELECT l FROM ResourceLink l WHERE l.myTargetResourcePid = :target_pid", ResourceLink.class);
query.setParameter("target_pid", theEntity.getId());
query.setMaxResults(1);
@ -2516,7 +2535,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
String sourceId = link.getSourceResource().getIdDt().toUnqualifiedVersionless().getValue();
String sourcePath = link.getSourcePath();
throw new PreconditionFailedException(
throw new ResourceVersionConflictException(
"Unable to delete " + targetId + " because at least one resource has a reference to this resource. First reference found was resource " + sourceId + " in path " + sourcePath);
}

View File

@ -33,6 +33,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
public class DaoConfig {
private boolean myAllowMultipleDelete;
private int myHardSearchLimit = 1000;
private int myHardTagListLimit = 1000;
private int myIncludeLimit = 2000;
@ -74,6 +75,14 @@ public class DaoConfig {
return mySubscriptionPollDelay;
}
public Long getSubscriptionPurgeInactiveAfterMillis() {
return mySubscriptionPurgeInactiveAfterMillis;
}
public boolean isAllowMultipleDelete() {
return myAllowMultipleDelete;
}
/**
* See {@link #setSubscriptionEnabled(boolean)}
*/
@ -81,6 +90,10 @@ public class DaoConfig {
return mySubscriptionEnabled;
}
public void setAllowMultipleDelete(boolean theAllowMultipleDelete) {
myAllowMultipleDelete = theAllowMultipleDelete;
}
public void setHardSearchLimit(int theHardSearchLimit) {
myHardSearchLimit = theHardSearchLimit;
}
@ -144,10 +157,6 @@ public class DaoConfig {
mySubscriptionPollDelay = theSubscriptionPollDelay;
}
public void setSubscriptionPurgeInactiveAfterSeconds(int theSeconds) {
setSubscriptionPurgeInactiveAfterMillis(theSeconds * DateUtils.MILLIS_PER_SECOND);
}
public void setSubscriptionPurgeInactiveAfterMillis(Long theMillis) {
if (theMillis != null) {
Validate.exclusiveBetween(0, Long.MAX_VALUE, theMillis);
@ -155,8 +164,8 @@ public class DaoConfig {
mySubscriptionPurgeInactiveAfterMillis = theMillis;
}
public Long getSubscriptionPurgeInactiveAfterMillis() {
return mySubscriptionPurgeInactiveAfterMillis;
public void setSubscriptionPurgeInactiveAfterSeconds(int theSeconds) {
setSubscriptionPurgeInactiveAfterMillis(theSeconds * DateUtils.MILLIS_PER_SECOND);
}
}

View File

@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.validation.DefaultProfileValidationSupport;
@ -105,11 +106,11 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
final ResourceTable entity = readEntityLatestVersion(theId);
OperationOutcome oo = new OperationOutcome();
try {
validateOkToDeleteOrThrowPreconditionFailedException(entity);
validateOkToDeleteOrThrowResourceVersionConflictException(entity);
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDiagnostics("Ok to delete");
} catch (PreconditionFailedException e) {
} catch (ResourceVersionConflictException e) {
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setDiagnostics(e.getMessage());
throw new PreconditionFailedException(e.getMessage(), oo);
throw new ResourceVersionConflictException(e.getMessage(), oo);
}
return new MethodOutcome(new IdDt(theId.getValue()), oo);
}

View File

@ -0,0 +1,63 @@
package ca.uhn.fhir.jpa.dao;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2015 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
public class FhirResourceDaoEncounterDstu2 extends FhirResourceDaoDstu2<Encounter>implements IFhirResourceDaoEncounter<Encounter> {
@Override
public IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
}
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setEverythingMode(EverythingModeEnum.ENCOUNTER);
paramMap.setSort(theSort);
paramMap.setLastUpdated(theLastUpdated);
if (theId != null) {
paramMap.add("_id", new StringParam(theId.getIdPart()));
}
ca.uhn.fhir.rest.server.IBundleProvider retVal = search(paramMap);
return retVal;
}
@Override
public IBundleProvider encounterTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
return encounterInstanceEverything(theServletRequest, null, theCount, theLastUpdated, theSort);
}
}

View File

@ -24,6 +24,7 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
@ -36,7 +37,7 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> {
@Override
public IBundleProvider everything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
@ -44,12 +45,19 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setEverythingMode(true);
paramMap.setEverythingMode(EverythingModeEnum.PATIENT);
paramMap.setSort(theSort);
paramMap.setLastUpdated(theLastUpdated);
paramMap.add("_id", new StringParam(theId.getIdPart()));
if (theId != null) {
paramMap.add("_id", new StringParam(theId.getIdPart()));
}
ca.uhn.fhir.rest.server.IBundleProvider retVal = search(paramMap);
return retVal;
}
@Override
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
return patientInstanceEverything(theServletRequest, null, theCount, theLastUpdated, theSort);
}
}

View File

@ -25,6 +25,8 @@ import javax.annotation.PostConstruct;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.ResourceTable;
@ -41,7 +43,10 @@ import ca.uhn.fhir.validation.ValidationResult;
public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDstu2<QuestionnaireResponse> {
@Autowired
@Qualifier("myFhirContextDstu2Hl7Org")
private FhirContext myRefImplCtx;
private Boolean myValidateResponses;
/**
@ -52,7 +57,6 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
try {
Class.forName("org.hl7.fhir.instance.model.QuestionnaireResponse");
myValidateResponses = true;
myRefImplCtx = FhirContext.forDstu2Hl7Org();
} catch (ClassNotFoundException e) {
myValidateResponses = Boolean.FALSE;
}

View File

@ -56,6 +56,7 @@ import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
@ -129,7 +130,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
ourLog.trace("Skipping search for subscription");
return;
}
ourLog.info("Subscription search from {} to {}", start, end);
ourLog.debug("Subscription {} search from {} to {}", new Object[] { subscription.getId().getIdPart(), new InstantDt(new Date(start)), new InstantDt(new Date(end)) });
DateRangeParam range = new DateRangeParam();
range.setLowerBound(new DateParam(QuantityCompararatorEnum.GREATERTHAN, start));
@ -176,7 +178,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
}
@Override
protected ResourceTable updateEntity(IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, Date theUpdateTime) {
protected ResourceTable updateEntity(IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime) {
ResourceTable retVal = super.updateEntity(theResource, theEntity, theUpdateHistory, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime);
Subscription resource = (Subscription) theResource;
@ -278,16 +281,17 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
@Override
public void purgeInactiveSubscriptions() {
Long purgeInactiveAfterMillis = getConfig().getSubscriptionPurgeInactiveAfterMillis();
if (getConfig().isSubscriptionEnabled()==false || purgeInactiveAfterMillis == null) {
if (getConfig().isSubscriptionEnabled() == false || purgeInactiveAfterMillis == null) {
return;
}
Date cutoff = new Date(System.currentTimeMillis() - purgeInactiveAfterMillis);
Collection<SubscriptionTable> toPurge = mySubscriptionTableDao.findInactiveBeforeCutoff(cutoff);
for (SubscriptionTable subscriptionTable : toPurge) {
final IdDt subscriptionId = subscriptionTable.getSubscriptionResource().getIdDt();
ourLog.info("Deleting inactive subscription {} - Created {}, last client poll {}", new Object[] { subscriptionId.toUnqualified(), subscriptionTable.getCreated(), subscriptionTable.getLastClientPoll() });
ourLog.info("Deleting inactive subscription {} - Created {}, last client poll {}",
new Object[] { subscriptionId.toUnqualified(), subscriptionTable.getCreated(), subscriptionTable.getLastClientPoll() });
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallback<Void>() {

View File

@ -28,10 +28,15 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
@ -46,32 +51,83 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.validation.DefaultProfileValidationSupport;
import ca.uhn.fhir.validation.ValidationSupportChain;
public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>implements IFhirResourceDaoValueSet<ValueSet> {
@Override
public ValueSet expand(IIdType theId, StringDt theFilter) {
ValueSet retVal = new ValueSet();
retVal.setDate(DateTimeDt.withCurrentTime());
@Autowired
private IJpaValidationSupport myJpaValidationSupport;
private ValidationSupportChain myValidationSupport;
@Autowired
@Qualifier("myFhirContextDstu2Hl7Org")
private FhirContext myRiCtx;
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
@Override
@PostConstruct
public void postConstruct() {
super.postConstruct();
myDefaultProfileValidationSupport = new DefaultProfileValidationSupport();
myValidationSupport = new ValidationSupportChain(myDefaultProfileValidationSupport, myJpaValidationSupport);
}
@Override
public ValueSet expand(IIdType theId, String theFilter) {
BaseHasResource sourceEntity = readEntity(theId);
if (sourceEntity == null) {
throw new ResourceNotFoundException(theId);
}
ValueSet source = (ValueSet) toResource(sourceEntity, false);
return expand(source, theFilter);
}
@Override
public ValueSet expandByIdentifier(String theUri, String theFilter) {
if (isBlank(theUri)) {
throw new InvalidRequestException("URI must not be blank or missing");
}
ValueSet source;
org.hl7.fhir.instance.model.ValueSet defaultValueSet = myDefaultProfileValidationSupport.fetchResource(myRiCtx, org.hl7.fhir.instance.model.ValueSet.class, theUri);
if (defaultValueSet != null) {
source = getContext().newJsonParser().parseResource(ValueSet.class, myRiCtx.newJsonParser().encodeResourceToString(defaultValueSet));
} else {
IBundleProvider ids = search(ValueSet.SP_URL, new UriParam(theUri));
if (ids.size() == 0) {
throw new InvalidRequestException("Unknown ValueSet URI: " + theUri);
}
source = (ValueSet) ids.getResources(0, 1).get(0);
}
return expand(source, theFilter);
}
@Override
public ValueSet expand(ValueSet source, String theFilter) {
ValueSet retVal = new ValueSet();
retVal.setDate(DateTimeDt.withCurrentTime());
/*
* Add composed concepts
*/
for (ComposeInclude nextInclude : source.getCompose().getInclude()) {
for (ComposeIncludeConcept next : nextInclude.getConcept()) {
if (theFilter == null || theFilter.isEmpty()) {
if (isBlank(theFilter)) {
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
} else {
String filter = theFilter.getValue().toLowerCase();
String filter = theFilter.toLowerCase();
if (next.getDisplay().toLowerCase().contains(filter) || next.getCode().toLowerCase().contains(filter)) {
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
}
@ -88,14 +144,13 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
}
return retVal;
}
private void addCompose(StringDt theFilter, ValueSet theValueSetToPopulate, ValueSet theSourceValueSet, CodeSystemConcept theConcept) {
if (theFilter == null || theFilter.isEmpty()) {
private void addCompose(String theFilter, ValueSet theValueSetToPopulate, ValueSet theSourceValueSet, CodeSystemConcept theConcept) {
if (isBlank(theFilter)) {
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
} else {
String filter = theFilter.getValue().toLowerCase();
String filter = theFilter.toLowerCase();
if (theConcept.getDisplay().toLowerCase().contains(filter) || theConcept.getCode().toLowerCase().contains(filter)) {
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
}
@ -133,7 +188,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
boolean haveIdentifierParam = theValueSetIdentifier != null && theValueSetIdentifier.isEmpty() == false;
if (theId != null) {
valueSetIds = Collections.singletonList((IIdType) theId);
valueSetIds = Collections.singletonList(theId);
} else if (haveIdentifierParam) {
Set<Long> ids = searchForIds(ValueSet.SP_IDENTIFIER, new TokenParam(null, theValueSetIdentifier.getValue()));
valueSetIds = new ArrayList<IIdType>();

View File

@ -222,6 +222,17 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
if (res != null) {
nextResourceId = res.getId();
if (nextResourceId.hasIdPart() == false) {
if (isNotBlank(nextEntry.getFullUrl())) {
nextResourceId = new IdDt(nextEntry.getFullUrl());
}
}
if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+\\:.*") && !isPlaceholder(nextResourceId)) {
throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'");
}
if (nextResourceId.hasIdPart() && !nextResourceId.hasResourceType() && !isPlaceholder(nextResourceId)) {
nextResourceId = new IdDt(toResourceName(res.getClass()), nextResourceId.getIdPart());
res.setId(nextResourceId);

View File

@ -0,0 +1,39 @@
package ca.uhn.fhir.jpa.dao;
import javax.servlet.http.HttpServletRequest;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* 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 org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
public interface IFhirResourceDaoEncounter<T extends IBaseResource> extends IFhirResourceDao<T> {
IBundleProvider encounterInstanceEverything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdate, SortSpec theSort);
IBundleProvider encounterTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSortSpec);
}

View File

@ -32,6 +32,8 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
public interface IFhirResourceDaoPatient<T extends IBaseResource> extends IFhirResourceDao<T> {
IBundleProvider everything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdate, SortSpec theSort);
IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IdDt theId, UnsignedIntDt theCount, DateRangeParam theLastUpdate, SortSpec theSort);
IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSortSpec);
}

View File

@ -32,8 +32,12 @@ import ca.uhn.fhir.model.primitive.UriDt;
public interface IFhirResourceDaoValueSet<T extends IBaseResource> extends IFhirResourceDao<T> {
ValueSet expand(IIdType theId, StringDt theFilter);
ValueSet expand(IIdType theId, String theFilter);
ValueSet expand(ValueSet theSource, String theFilter);
ValueSet expandByIdentifier(String theUri, String theFilter);
ValidateCodeResult validateCode(UriDt theValueSetIdentifier, IIdType theId, CodeDt theCode, UriDt theSystem, StringDt theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept);
public class ValidateCodeResult {

View File

@ -0,0 +1,27 @@
package ca.uhn.fhir.jpa.dao;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* 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.validation.IValidationSupport;
public interface IJpaValidationSupport extends IValidationSupport {
}

View File

@ -30,13 +30,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.validation.IValidationSupport;
public class JpaValidationSupportDstu2 implements IValidationSupport {
public class JpaValidationSupportDstu2 implements IJpaValidationSupport {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportDstu2.class);
private FhirContext myRiCtx = FhirContext.forDstu2Hl7Org();
@Autowired
@Qualifier("myFhirContextDstu2Hl7Org")
private FhirContext myRiCtx;
@Autowired
@Qualifier("myStructureDefinitionDaoDstu2")

View File

@ -52,6 +52,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
import ca.uhn.fhir.model.base.composite.BaseHumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.AddressDt;
import ca.uhn.fhir.model.dstu2.composite.BoundCodeableConceptDt;
@ -71,6 +72,7 @@ import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.RestfulSecurityServiceEnum;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
@ -79,7 +81,7 @@ import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISearchParamExtractor {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorDstu2.class);
public SearchParamExtractorDstu2(FhirContext theContext) {
super(theContext);
}
@ -115,7 +117,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/
@Override
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
@ -175,7 +178,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/
@Override
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
@ -222,12 +226,17 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
nextValue = newValue;
/*
* @SuppressWarnings("unchecked") PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>>)
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if (unit.isCompatible(UCUM.DAY)) {
* @SuppressWarnings("unchecked") PhysicsUnit<? extends
* org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends
* org.unitsofmeasurement.quantity.Quantity<?>>)
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if
* (unit.isCompatible(UCUM.DAY)) {
*
* @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit = (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY);
* double dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt newValue = new DurationDt(); newValue.setSystem(UCUM_NS);
* newValue.setCode(UCUM.DAY.getSymbol()); newValue.setValue(dayValue); nextValue=newValue; }
* @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit =
* (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY); double
* dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt newValue =
* new DurationDt(); newValue.setSystem(UCUM_NS); newValue.setCode(UCUM.DAY.getSymbol());
* newValue.setValue(dayValue); nextValue=newValue; }
*/
}
}
@ -269,7 +278,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/
@Override
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) {
@ -303,8 +313,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
continue;
}
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(),
nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(), nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else {
@ -323,7 +332,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/
@Override
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IResource theResource) {
@ -404,7 +414,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
*/
@Override
public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) {
@ -464,11 +475,11 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
systems.add(system);
codes.add(value);
}
if (isNotBlank(nextValue.getType().getText())) {
addStringParam(theEntity, retVal, nextSpDef, nextValue.getType().getText());
}
} else if (nextObject instanceof ContactPointDt) {
ContactPointDt nextValue = (ContactPointDt) nextObject;
if (nextValue.isEmpty()) {
@ -481,6 +492,14 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
}
systems.add(nextValue.getSystemElement().getValueAsString());
codes.add(nextValue.getValueElement().getValue());
} else if (nextObject instanceof BoundCodeDt) {
BoundCodeDt<?> obj = (BoundCodeDt<?>) nextObject;
String system = extractSystem(obj);
String code = obj.getValue();
if (isNotBlank(code)) {
systems.add(system);
codes.add(code);
}
} else if (nextObject instanceof IPrimitiveDatatype<?>) {
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
if (nextValue.isEmpty()) {
@ -503,7 +522,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
} else if (nextObject instanceof RestSecurity) {
// Conformance.security search param points to something kind of useless right now - This should probably be fixed.
// Conformance.security search param points to something kind of useless right now - This should probably
// be fixed.
RestSecurity sec = (RestSecurity) nextObject;
for (BoundCodeableConceptDt<RestfulSecurityServiceEnum> nextCC : sec.getService()) {
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
@ -588,9 +608,9 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
}
ourLog.trace("Adding param: {}, {}", resourceName, nextValue.getValue());
ResourceIndexedSearchParamUri nextEntity = new ResourceIndexedSearchParamUri(resourceName, nextValue.getValue());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else {
@ -605,17 +625,14 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
return retVal;
}
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity,
Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
for (CodingDt nextCoding : theCodeableConcept.getCoding()) {
extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding);
}
}
private void extractTokensFromCoding(List<String> theSystems, List<String> theCodes, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate,
RuntimeSearchParam theParameterDef, CodingDt nextCoding) {
private void extractTokensFromCoding(List<String> theSystems, List<String> theCodes, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef, CodingDt nextCoding) {
if (nextCoding != null && !nextCoding.isEmpty()) {
String nextSystem = nextCoding.getSystemElement().getValueAsString();
@ -632,4 +649,12 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
}
}
private static <T extends Enum<?>> String extractSystem(BoundCodeDt<T> theBoundCode) {
if (theBoundCode.getValueAsEnum() != null) {
IValueSetEnumBinder<T> binder = theBoundCode.getBinder();
return binder.toSystemString(theBoundCode.getValueAsEnum());
}
return null;
}
}

View File

@ -42,7 +42,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
private static final long serialVersionUID = 1L;
private Integer myCount;
private boolean myEverythingMode = false;
private EverythingModeEnum myEverythingMode = null;
private Set<Include> myIncludes;
private DateRangeParam myLastUpdated;
private Set<Include> myRevIncludes;
@ -124,7 +124,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
return mySort;
}
public boolean isEverythingMode() {
public EverythingModeEnum getEverythingMode() {
return myEverythingMode;
}
@ -132,7 +132,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
myCount = theCount;
}
public void setEverythingMode(boolean theConsolidateMatches) {
public void setEverythingMode(EverythingModeEnum theConsolidateMatches) {
myEverythingMode = theConsolidateMatches;
}
@ -164,4 +164,8 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
return b.toString();
}
public enum EverythingModeEnum {
PATIENT, ENCOUNTER
}
}

View File

@ -20,45 +20,79 @@ package ca.uhn.fhir.jpa.provider;
* #L%
*/
import java.util.Collections;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoEncounter;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.Constants;
public class BaseJpaResourceProviderEncounterDstu2 extends JpaResourceProviderDstu2<Encounter> {
/**
* Encounter/123/$everything
*/
//@formatter:off
@Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider EncounterInstanceEverything(
@Operation(name="everything", idempotent=true)
public ca.uhn.fhir.rest.server.IBundleProvider everything(
javax.servlet.http.HttpServletRequest theServletRequest,
@IdParam ca.uhn.fhir.model.primitive.IdDt theId,
javax.servlet.http.HttpServletRequest theServletRequest,
@IdParam
ca.uhn.fhir.model.primitive.IdDt theId,
@Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the size of those pages.")
@OperationParam(name="_count") ca.uhn.fhir.model.primitive.UnsignedIntDt theCount
){
@Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the size of those pages.")
@OperationParam(name = Constants.PARAM_COUNT)
ca.uhn.fhir.model.primitive.UnsignedIntDt theCount,
@Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
@Sort
SortSpec theSortSpec
) {
//@formatter:on
startRequest(theServletRequest);
try {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
}
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setEverythingMode(true);
paramMap.add("_id", new StringParam(theId.getIdPart()));
ca.uhn.fhir.rest.server.IBundleProvider retVal = getDao().search(paramMap);
return retVal;
return ((IFhirResourceDaoEncounter<Encounter>)getDao()).encounterInstanceEverything(theServletRequest, theId, theCount, theLastUpdated, theSortSpec);
} finally {
endRequest(theServletRequest);
}
}}
/**
* /Encounter/$everything
*/
//@formatter:off
@Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider EncounterTypeEverything(
javax.servlet.http.HttpServletRequest theServletRequest,
@Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the size of those pages.")
@OperationParam(name = Constants.PARAM_COUNT)
ca.uhn.fhir.model.primitive.UnsignedIntDt theCount,
@Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
@Sort
SortSpec theSortSpec
) {
//@formatter:on
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoEncounter<Encounter>)getDao()).encounterTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec);
} finally {
endRequest(theServletRequest);
}
}

View File

@ -33,8 +33,13 @@ import ca.uhn.fhir.rest.server.Constants;
public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu2<Patient> {
/**
* Patient/123/$everything
*/
//@formatter:off
@Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider everything(
public ca.uhn.fhir.rest.server.IBundleProvider patientInstanceEverything(
javax.servlet.http.HttpServletRequest theServletRequest,
@ -49,17 +54,46 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
// @OperationParam(name = Constants.PARAM_SORT, min=0, max=1)
@Sort
SortSpec theSortSpec
) {
//@formatter:on
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoPatient<Patient>)getDao()).everything(theServletRequest, theId, theCount, theLastUpdated, theSortSpec);
return ((IFhirResourceDaoPatient<Patient>)getDao()).patientInstanceEverything(theServletRequest, theId, theCount, theLastUpdated, theSortSpec);
} finally {
endRequest(theServletRequest);
}
}}
/**
* /Patient/$everything
*/
//@formatter:off
@Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider patientTypeEverything(
javax.servlet.http.HttpServletRequest theServletRequest,
@Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the size of those pages.")
@OperationParam(name = Constants.PARAM_COUNT)
ca.uhn.fhir.model.primitive.UnsignedIntDt theCount,
@Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
@Sort
SortSpec theSortSpec
) {
//@formatter:on
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoPatient<Patient>)getDao()).patientTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec);
} finally {
endRequest(theServletRequest);
}
}

View File

@ -45,19 +45,63 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
@Operation(name = "$expand", idempotent = true)
public ValueSet everything(
HttpServletRequest theServletRequest,
@IdParam IdDt theId,
@OperationParam(name = "filter") StringDt theFilter) {
@IdParam IdDt theId,
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter) {
//@formatter:on
startRequest(theServletRequest);
try {
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
return dao.expand(theId, theFilter);
return dao.expand(theId, toFilterString(theFilter));
} finally {
endRequest(theServletRequest);
}
}
//@formatter:off
@Operation(name = "$expand", idempotent = true)
public ValueSet everything(
HttpServletRequest theServletRequest,
@OperationParam(name="identifier", min=1, max=1) UriDt theIdentifier,
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter) {
//@formatter:on
startRequest(theServletRequest);
try {
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
} finally {
endRequest(theServletRequest);
}
}
//@formatter:off
@Operation(name = "$expand", idempotent = true)
public ValueSet everything(
HttpServletRequest theServletRequest,
@OperationParam(name="valueSet", min=1, max=1) ValueSet theValueSet,
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter) {
//@formatter:on
startRequest(theServletRequest);
try {
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
return dao.expand(theValueSet, toFilterString(theFilter));
} finally {
endRequest(theServletRequest);
}
}
private String toFilterString(StringDt theFilter) {
return theFilter != null ? theFilter.getValue() : null;
}
//@formatter:off
@Operation(name = "$validate-code", idempotent = true, returnParameters= {
@OperationParam(name="result", type=BooleanDt.class, min=1),

View File

@ -28,12 +28,14 @@ import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Conformance;
import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResource;
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResourceSearchParam;
import ca.uhn.fhir.model.dstu2.valueset.ConditionalDeleteStatusEnum;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SearchParamTypeEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
@ -48,11 +50,13 @@ public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
private IFhirSystemDao<Bundle> mySystemDao;
private volatile Conformance myCachedValue;
private RestfulServer myRestfulServer;
private DaoConfig myDaoConfig;
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao<Bundle> theSystemDao) {
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao<Bundle> theSystemDao, DaoConfig theDaoConfig) {
super(theRestfulServer);
myRestfulServer = theRestfulServer;
mySystemDao = theSystemDao;
myDaoConfig = theDaoConfig;
super.setCache(false);
}
@ -63,17 +67,23 @@ public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
Map<String, Long> counts = mySystemDao.getResourceCounts();
FhirContext ctx = myRestfulServer.getFhirContext();
retVal = super.getServerConformance(theRequest);
for (Rest nextRest : retVal.getRest()) {
for (RestResource nextResource : nextRest.getResource()) {
ConditionalDeleteStatusEnum conditionalDelete = nextResource.getConditionalDeleteElement().getValueAsEnum();
if (conditionalDelete == ConditionalDeleteStatusEnum.MULTIPLE_DELETES_SUPPORTED && myDaoConfig.isAllowMultipleDelete() == false) {
nextResource.setConditionalDelete(ConditionalDeleteStatusEnum.SINGLE_DELETES_SUPPORTED);
}
// Add resource counts
Long count = counts.get(nextResource.getTypeElement().getValueAsString());
if (count != null) {
nextResource.addUndeclaredExtension(false, ExtensionConstants.CONF_RESOURCE_COUNT, new DecimalDt(count));
}
// Add chained params
for (RestResourceSearchParam nextParam : nextResource.getSearchParam()) {
if (nextParam.getTypeElement().getValueAsEnum() == SearchParamTypeEnum.REFERENCE) {
@ -86,7 +96,7 @@ public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
}
}
}
}
}

View File

@ -69,8 +69,8 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
}
}
@Delete
public MethodOutcome delete(HttpServletRequest theRequest, @IdParam IdDt theResource, @ConditionalUrlParam String theConditional) {
@Delete()
public MethodOutcome delete(HttpServletRequest theRequest, @IdParam IdDt theResource, @ConditionalUrlParam(supportsMultiple=true) String theConditional) {
startRequest(theRequest);
try {
if (theConditional != null) {

View File

@ -103,6 +103,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@PersistenceContext()
protected EntityManager myEntityManager;
@Autowired
@Qualifier("myFhirContextDstu2")
protected FhirContext myFhirCtx;
@Autowired
@Qualifier("myImmunizationDaoDstu2")
@ -151,7 +152,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
protected PlatformTransactionManager myTxManager;
@Autowired
@Qualifier("myValueSetDaoDstu2")
protected IFhirResourceDao<ValueSet> myValueSetDao;
protected IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
@Before
public void beforeCreateInterceptor() {

View File

@ -1,17 +1,32 @@
package ca.uhn.fhir.jpa.dao;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.rest.server.IBundleProvider;
public class BaseJpaTest {
public static String loadClasspath(String resource) throws IOException {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream(resource);
if (bundleRes == null) {
throw new NullPointerException("Can not load " + resource);
}
String bundleStr = IOUtils.toString(bundleRes);
return bundleStr;
}
@AfterClass
public static void afterClassShutdownDerby() throws SQLException {
// try {
@ -35,6 +50,16 @@ public class BaseJpaTest {
return retVal;
}
protected List<IIdType> toUnqualifiedVersionlessIds(Bundle theFound) {
List<IIdType> retVal = new ArrayList<IIdType>();
for (Entry next : theFound.getEntry()) {
// if (next.getResource()!= null) {
retVal.add(next.getResource().getId().toUnqualifiedVersionless());
// }
}
return retVal;
}
protected List<IIdType> toUnqualifiedVersionlessIds(List<IBaseResource> theFound) {
List<IIdType> retVal = new ArrayList<IIdType>();
for (IBaseResource next : theFound) {

View File

@ -56,9 +56,12 @@ import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.Substance;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
@ -100,6 +103,19 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
assertEquals(0, results.size());
}
@Test
public void testCodeSearch() {
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
IIdType id = mySubscriptionDao.create(subs).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add(Subscription.SP_TYPE, new TokenParam(null, SubscriptionChannelTypeEnum.WEBSOCKET.getCode()));
map.add(Subscription.SP_STATUS, new TokenParam(null, SubscriptionStatusEnum.ACTIVE.getCode()));
assertThat(toUnqualifiedVersionlessIds(mySubscriptionDao.search(map)), contains(id));
}
@Test
public void testIndexNoDuplicatesString() {

View File

@ -97,6 +97,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
@ -683,7 +684,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
try {
myOrganizationDao.delete(orgId);
fail();
} catch (PreconditionFailedException e) {
} catch (ResourceVersionConflictException e) {
assertThat(e.getMessage(), containsString("Unable to delete Organization/" + orgId.getIdPart()
+ " because at least one resource has a reference to this resource. First reference found was resource Patient/" + patId.getIdPart() + " in path Patient.managingOrganization"));
}
@ -839,6 +840,8 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testHistoryByForcedId() {
IIdType idv1;
@ -2088,21 +2091,21 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID));
pm.setSort(new SortSpec(BaseResource.SP_RES_ID));
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID).setOrder(SortOrderEnum.ASC));
pm.setSort(new SortSpec(BaseResource.SP_RES_ID).setOrder(SortOrderEnum.ASC));
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(idMethodName, id1, id2, id3, id4));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", methodName));
pm.setSort(new SortSpec(Patient.SP_RES_ID).setOrder(SortOrderEnum.DESC));
pm.setSort(new SortSpec(BaseResource.SP_RES_ID).setOrder(SortOrderEnum.DESC));
actual = toUnqualifiedVersionlessIds(myPatientDao.search(pm));
assertEquals(5, actual.size());
assertThat(actual, contains(id4, id3, id2, id1, idMethodName));

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2ValidateTest.class);
@ -141,9 +142,9 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
OperationOutcome outcome=null;
try {
myOrganizationDao.validate(null, orgId, null, null, ValidationModeEnum.DELETE, null);
fail();
} catch (PreconditionFailedException e) {
myOrganizationDao.validate(null, orgId, null, null, ValidationModeEnum.DELETE, null);
fail();
} catch (ResourceVersionConflictException e) {
outcome= (OperationOutcome) e.getOperationOutcome();
}

View File

@ -1,68 +1,42 @@
package ca.uhn.fhir.jpa.dao;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStreamReader;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
import ca.uhn.fhir.jpa.provider.ResourceProviderDstu2Test;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/hapi-fhir-server-resourceproviders-dstu2.xml", "/fhir-jpabase-spring-test-config.xml" })
public class FhirResourceDaoValueSetDstu2Test {
public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoValueSetDstu2Test.class);
private static IIdType vsid;
private IIdType myExtensionalVsId;
@Autowired
private FhirContext myCtx;
@Autowired
@Qualifier("mySystemDaoDstu2")
private IFhirSystemDao<Bundle> mySystemDao;
@Autowired
@Qualifier("myValueSetDaoDstu2")
private IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
@Before
@Transactional
public void before01() {
if (vsid == null) {
FhirSystemDaoDstu2Test.doDeleteEverything(mySystemDao);
}
}
@Before
@Transactional
public void before02() {
if (vsid == null) {
ValueSet upload = myCtx.newXmlParser().parseResource(ValueSet.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/extensional-case-2.xml")));
upload.setId("");
vsid = myValueSetDao.create(upload).getId().toUnqualifiedVersionless();
}
public void before02() throws IOException {
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
upload.setId("");
myExtensionalVsId = myValueSetDao.create(upload).getId().toUnqualifiedVersionless();
}
@Test
@ -137,7 +111,7 @@ public class FhirResourceDaoValueSetDstu2Test {
@Test
public void testValidateCodeOperationByResourceIdAndCodeableConcept() {
UriDt valueSetIdentifier = null;
IIdType id = vsid;
IIdType id = myExtensionalVsId;
CodeDt code = null;
UriDt system = null;
StringDt display = null;
@ -151,7 +125,7 @@ public class FhirResourceDaoValueSetDstu2Test {
@Test
public void testValidateCodeOperationByResourceIdAndCodeAndSystem() {
UriDt valueSetIdentifier = null;
IIdType id = vsid;
IIdType id = myExtensionalVsId;
CodeDt code = new CodeDt("11378-7");
UriDt system = new UriDt("http://loinc.org");
StringDt display = null;
@ -163,11 +137,11 @@ public class FhirResourceDaoValueSetDstu2Test {
}
@Test
public void testValueSetExpandOperation() throws IOException {
public void testExpandById() throws IOException {
String resp;
ValueSet expanded = myValueSetDao.expand(vsid, null);
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null);
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
// @formatter:off
assertThat(resp,
@ -191,8 +165,8 @@ public class FhirResourceDaoValueSetDstu2Test {
* Filter with display name
*/
expanded = myValueSetDao.expand(vsid, new StringDt("systolic"));
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
@ -204,8 +178,8 @@ public class FhirResourceDaoValueSetDstu2Test {
* Filter with code
*/
expanded = myValueSetDao.expand(vsid, new StringDt("11378"));
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"));
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
@ -213,5 +187,34 @@ public class FhirResourceDaoValueSetDstu2Test {
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
}
@Test
public void testExpandByIdentifier() {
ValueSet expanded = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", "11378");
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
@Test
public void testExpandByValueSet() throws IOException {
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
ValueSet expanded = myValueSetDao.expand(toExpand, "11378");
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
}

View File

@ -18,7 +18,6 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
@ -28,7 +27,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
@ -346,8 +344,8 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
@Test
public void testTransactionWithCidIds2() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/dstu1_bundle.xml");
String bundleStr = IOUtils.toString(bundleRes);
String resource = "/dstu1_bundle.xml";
String bundleStr = loadClasspath(resource);
Bundle bundle = ourFhirContext.newXmlParser().parseBundle(bundleStr);
List<IResource> res = new ArrayList<IResource>();
@ -363,6 +361,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
assertThat(encodeResourceToString, not(containsString("smsp")));
}
/**
* This is the correct way to do this, not {@link #testTransactionWithCidIds()}
*/

View File

@ -31,6 +31,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
@ -44,7 +45,11 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryResponse;
import ca.uhn.fhir.model.dstu2.resource.Communication;
import ca.uhn.fhir.model.dstu2.resource.Medication;
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Patient;
@ -53,8 +58,11 @@ import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -354,6 +362,42 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
}
@Test
public void testTransactionCreateWithInvalidMatchUrl() {
String methodName = "testTransactionCreateWithInvalidMatchUrl";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
EntryRequest entry = request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
entry.setIfNoneExist("Patient?identifier identifier" + methodName);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?identifier identifiertestTransactionCreateWithInvalidMatchUrl] - URL is invalid (must not contain spaces)", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?identifier=");
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Invalid match URL[Patient?identifier=] - URL has no search parameters", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?foo=bar");
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?foo=bar] - Resource type Patient does not have a parameter with name: foo", e.getMessage());
}
}
public void testTransactionCreateWithDuplicateMatchUrl02() {
String methodName = "testTransactionCreateWithDuplicateMatchUrl02";
Bundle request = new Bundle();
@ -634,7 +678,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
try {
mySystemDao.transaction(request);
fail();
} catch (ResourceNotFoundException e) {
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("resource with match URL \"Patient?"));
}
}
@ -731,6 +775,68 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
}
public static void main(String[] args) {
Communication com = new Communication();
com.getSender().setReference("Patient/james");
com.addRecipient().setReference("Group/everyone");
com.addMedium().setText("Skype");
com.addPayload().setContent(new StringDt("Welcome to Connectathon 10! Any HAPI users feel free to grab me if you want to chat or need help!"));
System.out.println(FhirContext.forDstu2().newJsonParser().setPrettyPrint(true).encodeResourceToString(com));
}
@Test
public void testTransactionWithReferenceToCreateIfNoneExist() {
Bundle bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
Medication med = new Medication();
IdDt medId = IdDt.newRandomUuid();
med.setId(medId);
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
MedicationOrder mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
ourLog.info("Request:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
Bundle outcome = mySystemDao.transaction(bundle);
ourLog.info("Response:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
IdDt medId1 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId1 = new IdDt( outcome.getEntry().get(1).getResponse().getLocation());
/*
* Again!
*/
bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
med = new Medication();
medId = IdDt.newRandomUuid();
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
outcome = mySystemDao.transaction(bundle);
IdDt medId2 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId2 = new IdDt(outcome.getEntry().get(1).getResponse().getLocation());
assertTrue(medId1.isIdPartValidLong());
assertTrue(medId2.isIdPartValidLong());
assertTrue(medOrderId1.isIdPartValidLong());
assertTrue(medOrderId2.isIdPartValidLong());
assertEquals(medId1, medId2);
assertNotEquals(medOrderId1, medOrderId2);
}
@Test
public void testTransactionReadAndSearch() {
String methodName = "testTransactionReadAndSearch";

View File

@ -101,7 +101,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
restServer.setPlainProviders(mySystemProvider);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(restServer, mySystemDao);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(restServer, mySystemDao, myDaoConfig);
confProvider.setImplementationDescription("THIS IS THE DESC");
restServer.setServerConformanceProvider(confProvider);

View File

@ -4,6 +4,7 @@ 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.empty;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
@ -25,9 +26,7 @@ import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@ -69,12 +68,15 @@ import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
@ -89,6 +91,8 @@ import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
@ -97,6 +101,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
// private static JpaConformanceProvider ourConfProvider;
@Override
public void before() throws Exception {
super.before();
myDaoConfig.setAllowMultipleDelete(true);
}
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
@ -104,58 +115,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = ourClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// }
@Test
public void testSearchByIdOr() {
IIdType id1;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
}
IIdType id2;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
id2 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
}
//@formatter:off
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.RES_ID.matches().values(id1.getIdPart(), id2.getIdPart()))
.and(Patient.RES_ID.matches().value(id1.getIdPart()))
.execute();
//@formatter:on
assertThat(toIdListUnqualifiedVersionless(found), containsInAnyOrder(id1));
}
@Test
public void testBundleCreate() throws Exception {
IGenericClient client = ourClient;
@ -184,6 +143,78 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = ourClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// }
@Test
public void testCodeSearch() {
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
IIdType id = ourClient.create().resource(subs).execute().getId().toUnqualifiedVersionless();
//@formatter:off
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().code(SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().code(SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), contains(id));
//@formatter:off
resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().systemAndCode(SubscriptionChannelTypeEnum.WEBSOCKET.getSystem(), SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().systemAndCode(SubscriptionStatusEnum.ACTIVE.getSystem(), SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), contains(id));
//@formatter:off
resp = ourClient
.search()
.forResource(Subscription.class)
.where(Subscription.TYPE.exactly().systemAndCode(SubscriptionChannelTypeEnum.WEBSOCKET.getSystem(), SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
.and(Subscription.STATUS.exactly().systemAndCode("foo", SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:off
assertThat(toUnqualifiedVersionlessIds(resp), empty());
}
@Test
public void testCountParam() throws Exception {
// NB this does not get used- The paging provider has its own limits built in
@ -207,19 +238,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testCreateWithForcedId() throws IOException {
String methodName = "testCreateWithForcedId";
Patient p = new Patient();
p.addName().addFamily(methodName);
p.setId(methodName);
IIdType optId = ourClient.update().resource(p).execute().getId();
assertEquals(methodName, optId.getIdPart());
assertEquals("1", optId.getVersionIdPart());
}
@Test
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
ValueSet options = new ValueSet();
@ -328,6 +346,19 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testCreateWithForcedId() throws IOException {
String methodName = "testCreateWithForcedId";
Patient p = new Patient();
p.addName().addFamily(methodName);
p.setId(methodName);
IIdType optId = ourClient.update().resource(p).execute().getId();
assertEquals(methodName, optId.getIdPart());
assertEquals("1", optId.getVersionIdPart());
}
@Test
public void testDeepChaining() {
Location l1 = new Location();
@ -363,6 +394,63 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testDeleteConditionalMultiple() {
String methodName = "testDeleteConditionalMultiple";
myDaoConfig.setAllowMultipleDelete(false);
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("FAM1");
IIdType id1 = myPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("FAM2");
IIdType id2 = myPatientDao.create(p).getId().toUnqualifiedVersionless();
try {
//@formatter:off
ourClient
.delete()
.resourceConditionalByType(Patient.class)
.where(Patient.IDENTIFIER.exactly().code(methodName))
.execute();
//@formatter:on
fail();
} catch (PreconditionFailedException e) {
assertEquals("HTTP 412 Precondition Failed: Failed to DELETE resource with match URL \"Patient?identifier=testDeleteConditionalMultiple\" because this search matched 2 resources", e.getMessage());
}
// Not deleted yet..
ourClient.read().resource("Patient").withId(id1).execute();
ourClient.read().resource("Patient").withId(id2).execute();
myDaoConfig.setAllowMultipleDelete(true);
//@formatter:off
ourClient
.delete()
.resourceConditionalByType(Patient.class)
.where(Patient.IDENTIFIER.exactly().code(methodName))
.execute();
//@formatter:on
try {
ourClient.read().resource("Patient").withId(id1).execute();
fail();
} catch (ResourceGoneException e) {
// good
}
try {
ourClient.read().resource("Patient").withId(id2).execute();
fail();
} catch (ResourceGoneException e) {
// good
}
}
@Test
public void testDeleteInvalidReference() throws IOException {
HttpDelete delete = new HttpDelete(ourServerBase + "/Patient");
@ -376,7 +464,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
response.close();
}
}
@Test
public void testDeleteResourceConditional1() throws IOException {
String methodName = "testDeleteResourceConditional1";
@ -416,7 +504,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
/**
* Based on email from Rene Spronk
*/
@ -543,11 +631,133 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testEverythingEncounterInstance() throws Exception {
String methodName = "testEverythingEncounterInstance";
Organization org1parent = new Organization();
org1parent.setId("org1parent");
org1parent.setName(methodName + "1parent");
IIdType orgId1parent = ourClient.update().resource(org1parent).execute().getId().toUnqualifiedVersionless();
Organization org1 = new Organization();
org1.setName(methodName + "1");
org1.getPartOf().setReference(orgId1parent);
IIdType orgId1 = ourClient.create().resource(org1).execute().getId().toUnqualifiedVersionless();
Patient p = new Patient();
p.addName().addFamily(methodName);
p.getManagingOrganization().setReference(orgId1);
IIdType patientId = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Organization org2 = new Organization();
org2.setName(methodName + "1");
IIdType orgId2 = ourClient.create().resource(org2).execute().getId().toUnqualifiedVersionless();
Device dev = new Device();
dev.setModel(methodName);
dev.getOwner().setReference(orgId2);
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Location locParent = new Location();
locParent.setName(methodName+"Parent");
IIdType locPId = ourClient.create().resource(locParent).execute().getId().toUnqualifiedVersionless();
Location locChild = new Location();
locChild.setName(methodName);
locChild.getPartOf().setReference(locPId);
IIdType locCId = ourClient.create().resource(locChild).execute().getId().toUnqualifiedVersionless();
Encounter encU = new Encounter();
encU.getPatient().setReference(patientId);
encU.addLocation().getLocation().setReference(locCId);
IIdType encUId = ourClient.create().resource(encU).execute().getId().toUnqualifiedVersionless();
Encounter enc = new Encounter();
enc.getPatient().setReference(patientId);
enc.addLocation().getLocation().setReference(locCId);
IIdType encId = ourClient.create().resource(enc).execute().getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.getSubject().setReference(patientId);
obs.getDevice().setReference(devId);
obs.getEncounter().setReference(encId);
IIdType obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onInstance(encId).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IIdType> ids = toUnqualifiedVersionlessIds(b);
assertThat(ids, containsInAnyOrder(patientId, encId, orgId1, orgId2, orgId1parent, locPId, locCId, obsId, devId));
assertThat(ids, not(containsInRelativeOrder(encUId)));
ourLog.info(ids.toString());
}
@Test
public void testEverythingEncounterType() throws Exception {
String methodName = "testEverythingEncounterInstance";
Organization org1parent = new Organization();
org1parent.setId("org1parent");
org1parent.setName(methodName + "1parent");
IIdType orgId1parent = ourClient.update().resource(org1parent).execute().getId().toUnqualifiedVersionless();
Organization org1 = new Organization();
org1.setName(methodName + "1");
org1.getPartOf().setReference(orgId1parent);
IIdType orgId1 = ourClient.create().resource(org1).execute().getId().toUnqualifiedVersionless();
Patient p = new Patient();
p.addName().addFamily(methodName);
p.getManagingOrganization().setReference(orgId1);
IIdType patientId = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Organization org2 = new Organization();
org2.setName(methodName + "1");
IIdType orgId2 = ourClient.create().resource(org2).execute().getId().toUnqualifiedVersionless();
Device dev = new Device();
dev.setModel(methodName);
dev.getOwner().setReference(orgId2);
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Location locParent = new Location();
locParent.setName(methodName+"Parent");
IIdType locPId = ourClient.create().resource(locParent).execute().getId().toUnqualifiedVersionless();
Location locChild = new Location();
locChild.setName(methodName);
locChild.getPartOf().setReference(locPId);
IIdType locCId = ourClient.create().resource(locChild).execute().getId().toUnqualifiedVersionless();
Encounter encU = new Encounter();
encU.addIdentifier().setValue(methodName);
IIdType encUId = ourClient.create().resource(encU).execute().getId().toUnqualifiedVersionless();
Encounter enc = new Encounter();
enc.getPatient().setReference(patientId);
enc.addLocation().getLocation().setReference(locCId);
IIdType encId = ourClient.create().resource(enc).execute().getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.getSubject().setReference(patientId);
obs.getDevice().setReference(devId);
obs.getEncounter().setReference(encId);
IIdType obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onType(Encounter.class).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IIdType> ids = toUnqualifiedVersionlessIds(b);
assertThat(ids, containsInAnyOrder(patientId, encUId, encId, orgId1, orgId2, orgId1parent, locPId, locCId, obsId, devId));
ourLog.info(ids.toString());
}
/**
* See #147
*/
@Test
public void testEverythingDoesntRepeatPatient() throws Exception {
public void testEverythingPatientDoesntRepeatPatient() throws Exception {
ca.uhn.fhir.model.dstu2.resource.Bundle b;
b = myFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
@ -601,14 +811,159 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(ids.size(), greaterThan(10));
}
}
/**
* Test for #226
*/
@Test
public void testEverythingPatientIncludesBackReferences() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
Medication med = new Medication();
med.getCode().setText(methodName);
IIdType medId = myMedicationDao.create(med).getId().toUnqualifiedVersionless();
Patient pat = new Patient();
pat.addAddress().addLine(methodName);
IIdType patId = myPatientDao.create(pat).getId().toUnqualifiedVersionless();
MedicationOrder mo = new MedicationOrder();
mo.getPatient().setReference(patId);
mo.setMedication(new ResourceReferenceDt(medId));
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onInstance(patId).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IIdType> ids = toUnqualifiedVersionlessIds(b);
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(patId, medId, moId));
}
/**
* See #148
*/
@Test
public void testEverythingPatientIncludesCondition() throws Exception {
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
Patient p = new Patient();
p.setId("1");
b.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
Condition c = new Condition();
c.getPatient().setReference("Patient/1");
b.addEntry().setResource(c).getRequest().setMethod(HTTPVerbEnum.POST);
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
IdDt patientId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
assertEquals("Patient", patientId.getResourceType());
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IdDt> ids = new ArrayList<IdDt>();
for (Entry next : b.getEntry()) {
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
ids.add(toAdd);
}
assertThat(ids.toString(), containsString("Patient/"));
assertThat(ids.toString(), containsString("Condition/"));
}
@Test
public void testEverythingPatientOperation() throws Exception {
String methodName = "testEverythingOperation";
Organization org1parent = new Organization();
org1parent.setId("org1parent");
org1parent.setName(methodName + "1parent");
IIdType orgId1parent = ourClient.update().resource(org1parent).execute().getId().toUnqualifiedVersionless();
Organization org1 = new Organization();
org1.setName(methodName + "1");
org1.getPartOf().setReference(orgId1parent);
IIdType orgId1 = ourClient.create().resource(org1).execute().getId().toUnqualifiedVersionless();
Patient p = new Patient();
p.addName().addFamily(methodName);
p.getManagingOrganization().setReference(orgId1);
IIdType patientId = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Organization org2 = new Organization();
org2.setName(methodName + "1");
IIdType orgId2 = ourClient.create().resource(org2).execute().getId().toUnqualifiedVersionless();
Device dev = new Device();
dev.setModel(methodName);
dev.getOwner().setReference(orgId2);
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.getSubject().setReference(patientId);
obs.getDevice().setReference(devId);
IIdType obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless();
Encounter enc = new Encounter();
enc.getPatient().setReference(patientId);
IIdType encId = ourClient.create().resource(enc).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IIdType> ids = toUnqualifiedVersionlessIds(b);
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2, orgId1parent));
ourLog.info(ids.toString());
}
@Test
public void testEverythingPatientType() throws Exception {
String methodName = "testEverythingPatientType";
Organization o1 = new Organization();
o1.setName(methodName+"1");
IIdType o1Id = ourClient.create().resource(o1).execute().getId().toUnqualifiedVersionless();
Organization o2 = new Organization();
o2.setName(methodName+"2");
IIdType o2Id = ourClient.create().resource(o2).execute().getId().toUnqualifiedVersionless();
Patient p1 = new Patient();
p1.addName().addFamily(methodName+"1");
p1.getManagingOrganization().setReference(o1Id);
IIdType p1Id = ourClient.create().resource(p1).execute().getId().toUnqualifiedVersionless();
Patient p2 = new Patient();
p2.addName().addFamily(methodName+"2");
p2.getManagingOrganization().setReference(o2Id);
IIdType p2Id = ourClient.create().resource(p2).execute().getId().toUnqualifiedVersionless();
Condition c1 = new Condition();
c1.getPatient().setReference(p1Id);
IIdType c1Id = ourClient.create().resource(c1).execute().getId().toUnqualifiedVersionless();
Condition c2 = new Condition();
c2.getPatient().setReference(p2Id);
IIdType c2Id = ourClient.create().resource(c2).execute().getId().toUnqualifiedVersionless();
Condition c3 = new Condition();
c3.addIdentifier().setValue(methodName+"3");
IIdType c3Id = ourClient.create().resource(c3).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onType(Patient.class).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IIdType> ids = toUnqualifiedVersionlessIds(b);
assertThat(ids, containsInAnyOrder(o1Id, o2Id, p1Id, p2Id, c1Id, c2Id));
assertThat(ids, not(containsInRelativeOrder(c3Id)));
}
@Test
public void testEverythingWithLastUpdatedAndSort() throws Exception {
public void testEverythingPatientWithLastUpdatedAndSort() throws Exception {
String methodName = "testEverythingWithLastUpdatedAndSort";
long time0 = System.currentTimeMillis();
Thread.sleep(10);
Organization org = new Organization();
org.setName(methodName);
IIdType oId = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
@ -691,122 +1046,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
/**
* See #148
*/
@Test
public void testEverythingIncludesCondition() throws Exception {
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
Patient p = new Patient();
p.setId("1");
b.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
Condition c = new Condition();
c.getPatient().setReference("Patient/1");
b.addEntry().setResource(c).getRequest().setMethod(HTTPVerbEnum.POST);
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
IdDt patientId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
assertEquals("Patient", patientId.getResourceType());
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
List<IdDt> ids = new ArrayList<IdDt>();
for (Entry next : b.getEntry()) {
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
ids.add(toAdd);
}
assertThat(ids.toString(), containsString("Patient/"));
assertThat(ids.toString(), containsString("Condition/"));
}
/**
* Test for #226
*/
@Test
public void testEverythingIncludesBackReferences() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
Medication med = new Medication();
med.getCode().setText(methodName);
IIdType medId = myMedicationDao.create(med).getId().toUnqualifiedVersionless();
Patient pat = new Patient();
pat.addAddress().addLine(methodName);
IIdType patId = myPatientDao.create(pat).getId().toUnqualifiedVersionless();
MedicationOrder mo = new MedicationOrder();
mo.getPatient().setReference(patId);
mo.setMedication(new ResourceReferenceDt(medId));
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onInstance(patId).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
Set<IdDt> ids = toIdList(b);
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(patId, medId, moId));
}
@Test
public void testEverythingOperation() throws Exception {
String methodName = "testEverythingOperation";
Organization org1parent = new Organization();
org1parent.setId("org1parent");
org1parent.setName(methodName + "1parent");
IIdType orgId1parent = ourClient.update().resource(org1parent).execute().getId().toUnqualifiedVersionless();
Organization org1 = new Organization();
org1.setName(methodName + "1");
org1.getPartOf().setReference(orgId1parent);
IIdType orgId1 = ourClient.create().resource(org1).execute().getId().toUnqualifiedVersionless();
Patient p = new Patient();
p.addName().addFamily(methodName);
p.getManagingOrganization().setReference(orgId1);
IIdType patientId = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Organization org2 = new Organization();
org2.setName(methodName + "1");
IIdType orgId2 = ourClient.create().resource(org2).execute().getId().toUnqualifiedVersionless();
Device dev = new Device();
dev.setModel(methodName);
dev.getOwner().setReference(orgId2);
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.getSubject().setReference(patientId);
obs.getDevice().setReference(devId);
IIdType obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless();
Encounter enc = new Encounter();
enc.getPatient().setReference(patientId);
IIdType encId = ourClient.create().resource(enc).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
Set<IdDt> ids = toIdList(b);
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2, orgId1parent));
ourLog.info(ids.toString());
}
private Set<IdDt> toIdList(ca.uhn.fhir.model.dstu2.resource.Bundle b) {
Set<IdDt> ids = new HashSet<IdDt>();
for (Entry next : b.getEntry()) {
ids.add(next.getResource().getId().toUnqualifiedVersionless());
}
return ids;
}
@Test
public void testGetResourceCountsOperation() throws Exception {
@ -886,6 +1125,29 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testMetaOperations() throws Exception {
String methodName = "testMetaOperations";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
assertEquals(0, meta.getTag().size());
MetaDt inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
assertEquals(1, meta.getTag().size());
inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
assertEquals(0, meta.getTag().size());
}
@Test
public void testMetaOperationWithNoMetaParameter() throws Exception {
Patient p = new Patient();
@ -930,29 +1192,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testMetaOperations() throws Exception {
String methodName = "testMetaOperations";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
assertEquals(0, meta.getTag().size());
MetaDt inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
assertEquals(1, meta.getTag().size());
inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
assertEquals(0, meta.getTag().size());
}
/**
* Test for issue #60
*/
@ -1093,6 +1332,33 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testSearchByIdOr() {
IIdType id1;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
}
IIdType id2;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
id2 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
}
//@formatter:off
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.RES_ID.matches().values(id1.getIdPart(), id2.getIdPart()))
.and(Patient.RES_ID.matches().value(id1.getIdPart()))
.execute();
//@formatter:on
assertThat(toIdListUnqualifiedVersionless(found), containsInAnyOrder(id1));
}
@Test
public void testSearchByResourceChain() {
@ -1297,7 +1563,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
o.getCode().setText("testSearchWithInvalidSort");
myObservationDao.create(o);
//@formatter:off
Bundle found = ourClient
ourClient
.search()
.forResource(Observation.class)
.sort().ascending(Observation.CODE_VALUE_QUANTITY) // composite sort not supported yet
@ -1552,6 +1818,21 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testTransaction() throws Exception {
String contents = loadClasspath("/update.xml");
HttpPost post = new HttpPost(ourServerBase);
post.setEntity(new StringEntity(contents, ContentType.create("application/xml+fhir", "UTF-8")));
CloseableHttpResponse resp = ourHttpClient.execute(post);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
String output= IOUtils.toString(resp.getEntity().getContent());
ourLog.info(output);
} finally {
resp.close();
}
}
@Test
public void testTryToCreateResourceWithReferenceThatDoesntExist() {
Patient p1 = new Patient();
@ -1568,6 +1849,27 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testUpdateInvalidReference() throws IOException, Exception {
String methodName = "testUpdateInvalidReference";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut post = new HttpPut(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("<pre>Can not update a resource with no ID</pre>"));
assertThat(responseString, containsString("<OperationOutcome"));
assertEquals(400, response.getStatusLine().getStatusCode());
} finally {
response.close();
}
}
@Test
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
@ -1629,28 +1931,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testUpdateInvalidReference() throws IOException, Exception {
String methodName = "testUpdateInvalidReference";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut post = new HttpPut(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("<pre>Can not update a resource with no ID</pre>"));
assertThat(responseString, containsString("<OperationOutcome"));
assertEquals(400, response.getStatusLine().getStatusCode());
} finally {
response.close();
}
}
@Test
public void testUpdateResourceWithPrefer() throws IOException, Exception {

View File

@ -0,0 +1,161 @@
package ca.uhn.fhir.jpa.provider;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test;
import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test {
private IIdType myExtensionalVsId;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2ValueSetTest.class);
@Before
@Transactional
public void before02() throws IOException {
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
upload.setId("");
myExtensionalVsId = myValueSetDao.create(upload).getId().toUnqualifiedVersionless();
}
@Test
public void testExpandById() throws IOException {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
.named("expand")
.withNoParameters(Parameters.class)
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
// @formatter:off
assertThat(resp,
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
"<expansion>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>",
"</contains>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"8450-9\"/>",
"<display value=\"Systolic blood pressure--expiration\"/>",
"</contains>",
"</expansion>"
));
//@formatter:on
/*
* Filter with display name
*/
//@formatter:off
respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
.named("expand")
.withParameter(Parameters.class, "filter", new StringDt("systolic"))
.execute();
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
/*
* Filter with code
*/
//@formatter:off
respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
.named("expand")
.withParameter(Parameters.class, "filter", new StringDt("11378"))
.execute();
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
}
@Test
public void testExpandByIdentifier() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
.named("expand")
.withParameter(Parameters.class, "identifier", new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
.andParameter("filter", new StringDt("11378"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
@Test
public void testExpandByValueSet() throws IOException {
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml");
//@formatter:off
Parameters respParam = ourClient
.operation()
.onInstance(myExtensionalVsId)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringDt("11378"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
}
}

View File

@ -8,6 +8,7 @@ import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@ -26,9 +27,11 @@ 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.dstu2.resource.OperationDefinition;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class SystemProviderDstu2Test extends BaseJpaTest {
@ -38,6 +41,36 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
private static FhirContext ourCtx;
private static IGenericClient ourClient;
@Test
public void testTransactionFromBundle4() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle.xml");
String bundle = IOUtils.toString(bundleRes);
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
ourLog.info(response);
Bundle bundleResp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
IdDt id = new IdDt(bundleResp.getEntry().get(0).getResponse().getLocation());
assertEquals("Patient", id.getResourceType());
assertTrue(id.hasIdPart());
assertTrue(id.isIdPartValidLong());
assertTrue(id.hasVersionIdPart());
assertTrue(id.isVersionIdPartValidLong());
}
@Test
public void testTransactionFromBundle5() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle2.xml");
String bundle = IOUtils.toString(bundleRes);
try {
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
fail();
} catch (InvalidRequestException e) {
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
assertEquals("Invalid placeholder ID found: uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'", oo.getIssue().get(0).getDiagnostics());
assertEquals("processing", oo.getIssue().get(0).getCode());
}
}
@Test
public void testTransactionFromBundle() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">A selection of codes from http://loinc.org</div>
</text>
<url value="http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"/>
<identifier>
<value
value="http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2" />

View File

@ -0,0 +1,107 @@
<Bundle xmlns="http://hl7.org/fhir">
<id value="20151003220331"/>
<type value="transaction"/>
<entry>
<fullUrl value="urn:uuid:abd7a623-699e-46b5-5f5f-8d1d79fa33e6"/>
<resource>
<Patient>
<identifier>
<use value="usual"/>
<type>
<coding>
<system value="http://hl7.org/fhir/identifier-type"/>
<code value="NH"/>
</coding>
</type>
<system value="urn:oid:2.16.840.1.113883.2.1.4.1"/>
<value value="23455457476474754545"/>
<assigner>
<display value="NHS"/>
</assigner>
</identifier>
<identifier>
<use value="usual"/>
<type>
<coding>
<system value="http://hl7.org/fhir/identifier-type"/>
<code value="MR"/>
</coding>
</type>
<system value="http://www.ghh.org/identifiers/"/>
<value value="4567567567"/>
<assigner>
<display value="TCPAS"/>
</assigner>
</identifier>
<name>
<use value="official"/>
<family value="Connectathon"/>
<given value="Ann"/>
</name>
<telecom>
<system value="phone"/>
<value value="277543"/>
<use value="home"/>
</telecom>
<gender value="female"/>
<birthDate value="1928-05-24"/>
<address>
<line value="22 Stable Road"/>
<city value="Whitstable"/>
<state value="Kent"/>
<country value="CR5 1EL"/>
</address>
<contact>
<relationship>
<coding>
<system value="http://hl7.org/fhir/patient-contact-relationship"/>
<code value="parent"/>
</coding>
</relationship>
<name>
<family value="Connectathon"/>
<given value="Joe"/>
</name>
</contact>
</Patient>
</resource>
<request>
<method value="PUT"/>
<url value="/Patient?identifier=http://www.ghh.org/identifiers/|4567567567"/>
</request>
</entry>
<entry>
<fullUrl value="urn:uuid:491aabbf-fcff-4697-5bb2-84e856d5786b"/>
<resource>
<Encounter>
<identifier>
<use value="usual"/>
<type>
<coding>
<system value="http://hl7.org/fhir/identifier-type"/>
<code value="MR"/>
</coding>
</type>
<system value="http://general-hospital.co.uk/Identifiers/"/>
<value value="123447878787866666"/>
<assigner>
<display value="GENHOS"/>
</assigner>
</identifier>
<status value="in-progress"/>
<class value="inpatient"/>
<patient>
<reference value="urn:uuid:abd7a623-699e-46b5-5f5f-8d1d79fa33e6"/>
<display value="Connectathon, Ann(*24.05.1928)"/>
</patient>
<period>
<start value="2015-05-02T09:00:00+01:00"/>
</period>
</Encounter>
</resource>
<request>
<method value="PUT"/>
<url value="/Encounter?identifier=http://general-hospital.co.uk/Identifiers/|123447878787866666"/>
</request>
</entry>
</Bundle>

View File

@ -0,0 +1,73 @@
<Bundle xmlns="http://hl7.org/fhir" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<type value="transaction"/>
<entry>
<fullUrl value="uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d"/>
<resource>
<Patient>
<text>
<status value="generated"/>
<xhtml:div>
<xhtml:img src="http://pbs.twimg.com/profile_images/544507893991485440/r_vo3uj2_bigger.png" alt="Twitter Avatar"/>
@fhirabend
</xhtml:div>
</text>
<identifier>
<use value="secondary"/>
<system value="http://twitter.com"/>
<value value="2922960201"/>
</identifier>
<name>
<family value="fhirabend"/>
</name>
<photo>
<url value="http://pbs.twimg.com/profile_images/544507893991485440/r_vo3uj2_bigger.png"/>
</photo>
</Patient>
</resource>
<request>
<method value="PUT"/>
<url value="Patient?identifier=http://twitter.com|2922960201"/>
</request>
</entry>
<entry>
<resource>
<Communication>
<meta>
<profile value="http://foo/Profile1"/>
<tag>
<system value="http://twitter.com"/>
<code value="http://twitter.com/hashtag/FHIR"/>
<display value="#FHIR"/>
</tag>
</meta>
<text>
<status value="generated"/>
<xhtml:div>
<xhtml:b> @fhirabend:</xhtml:b>
RT @kainamti: Motto of the FHIR calendar 2016: the #FHIR is strong in you @HL7 http://t.co/E03Y3NIjME
</xhtml:div>
</text>
<identifier>
<system value="http://twitter.com"/>
<value value="650408456562823168"/>
</identifier>
<sender>
<reference value="uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d"/>
</sender>
<payload>
<contentString value="RT @kainamti: Motto of the FHIR calendar 2016: the #FHIR is strong in you @HL7 http://t.co/E03Y3NIjME"/>
</payload>
<medium>
<coding>
<code value="Twitter"/>
</coding>
</medium>
<sent value="2015-10-03T22:33:54+02:00"/>
</Communication>
</resource>
<request>
<method value="PUT"/>
<url value="Communication?identifier=http://twitter.com|650408456562823168"/>
</request>
</entry>
</Bundle>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bundle xmlns="http://hl7.org/fhir">
<id value="bundle-transaction"/>
<meta>
<lastUpdated value="2014-08-18T01:43:30Z"/>
</meta>
<type value="transaction"/>
<entry>
<fullUrl value="urn:uuid:61ebe359-bfdc-4613-8bf2-c5e300945f0b"/>
<resource>
<Medication>
<code>
<coding>
<system value="http://snomed.info/sct"/>
<code value="408036003"/>
<display value="Rosuvastatin 10mg tablet"/>
</coding>
</code>
</Medication>
</resource>
<request>
<method value="POST"/>
<url value="Medication"/>
<ifNoneExist value="code=408036003"/>
</request>o
</entry>
</Bundle>

View File

@ -98,7 +98,6 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- You may not need this if you are deploying to an application server which provides database connection pools itself. -->
@ -148,6 +147,11 @@
<artifactId>jetty-webapp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
</dependencies>
@ -166,6 +170,9 @@
<webApp>
<contextPath>/hapi-fhir-jpaserver-example</contextPath>
</webApp>
<webAppConfig>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</webAppConfig>
</configuration>
</plugin>
</plugins>

View File

@ -9,6 +9,7 @@ import org.springframework.web.context.WebApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
@ -80,7 +81,7 @@ public class JpaServerDemo extends RestfulServer {
setServerConformanceProvider(confProvider);
} else {
IFhirSystemDao<Bundle> systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, myAppCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("Example Server");
setServerConformanceProvider(confProvider);
}

View File

@ -14,6 +14,7 @@ import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
@ -83,7 +84,7 @@ public class TestRestfulServer extends RestfulServer {
systemProviderDstu2 = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
etagSupport = ETagSupportEnum.ENABLED;
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, myAppCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription(implDesc);
setServerConformanceProvider(confProvider);
baseUrlProperty = "fhir.baseurl.dstu2";

View File

@ -1,10 +1,19 @@
package ca.uhn.fhirtest.mvc;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.to.BaseController;
import ca.uhn.fhir.to.model.HomeRequest;
@ -21,6 +30,30 @@ public class SubscriptionPlaygroundController extends BaseController {
ourLog.info(logPrefix(theModel) + "Displayed subscriptions playground page");
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor);
//@formatter:off
Bundle resp = client
.search()
.forResource(Subscription.class)
// .where(Subscription.TYPE.exactly().code(SubscriptionChannelTypeEnum.WEBSOCKET.getCode()))
// .and(Subscription.STATUS.exactly().code(SubscriptionStatusEnum.ACTIVE.getCode()))
.returnBundle(Bundle.class)
.sort().descending(Subscription.TYPE)
.sort().ascending(Subscription.STATUS)
.execute();
//@formatter:off
List<Subscription> subscriptions = new ArrayList<Subscription>();
for (Entry next : resp.getEntry()) {
if (next.getResource() instanceof Subscription) {
subscriptions.add((Subscription) next.getResource());
}
}
theModel.put("subscriptions", subscriptions);
return "subscriptions";
}

View File

@ -9,6 +9,24 @@
</encoder>
</appender>
<appender name="SUBSCRIPTION_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<file>${fhir.logdir}/subscription.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${fhir.logdir}/subscription.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{req.remoteAddr}] [%X{req.userAgent}] %-5level %logger{36} %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
@ -39,19 +57,25 @@
</encoder>
</appender>
<logger name="fhirtest.access" level="INFO" additivity="false">
<appender-ref ref="ACCESS" />
</logger>
<logger name="fhirtest.access" level="INFO" additivity="false">
<appender-ref ref="ACCESS"/>
</logger>
<logger name="ca.uhn.fhir.jpa.dao.FhirResourceDaoSubscriptionDstu2" additivity="true" level="debug">
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>
<logger name="ca.uhn.fhir.jpa.subscription" additivity="true" level="debug">
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>
<logger name="org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator" additivity="false" level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="FILE"/>
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>
</appender>
<root level="INFO">
<appender-ref ref="FILE" />
<appender-ref ref="FILE"/>
</root>
</configuration>

View File

@ -17,6 +17,7 @@
<property name="subscriptionEnabled" value="true"></property>
<property name="subscriptionPurgeInactiveAfterSeconds" value="3600" /> <!-- 1 hour -->
<property name="subscriptionPollDelay" value="5000"></property>
<property name="allowMultipleDelete" value="true"/>
</bean>
<util:list id="myServerInterceptors">
@ -54,6 +55,8 @@
<property name="loggerName" value="fhirtest.access"/>
<property name="messageFormat"
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"/>
<property name="logExceptions" value="true"/>
<property name="errorMessageFormat" value="ERROR - ${requestVerb} ${requestUrl}"/>
</bean>
</beans>

View File

@ -30,99 +30,153 @@
</div>
<div class="panel-body">
<div class="container-fluid">
<p>
This page is a test playground for WebSocket Subscriptions
</p>
<p>This page is a test playground for WebSocket
Subscriptions</p>
</div>
</div>
</div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#wss"
aria-controls="wss" role="tab" data-toggle="tab">Static
Websocket</a></li>
<li role="presentation"><a href="#wsd" aria-controls="wsd"
role="tab" data-toggle="tab">Dynamic Websocket</a></li>
</ul>
<!-- Subscription Creation -->
<div id="subscription_creation">
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="wss">...1</div>
<!-- Dynamic WebSocket -->
<div role="tabpanel" class="tab-pane" id="wsd">
<script type="text/javascript">
function dwsCreate() {
try {
var socket = new WebSocket("ws://localhost:8888/websocket/dstu2");
alert('Socket Status: '+socket.readyState);
socket.onopen = function() {
alert("Opening Socket: " + socket.readyState);
socket.send("bind Observation?");
}
socket.onmessage = function(msg) {
alert("New message: " + msg);
}
socket.onerror = function(error) {
alert("error: " + error);
}
} catch (exception) {
alert('Error'+exception);
}
return false;
}
</script>
<div class="row">
<div class="col-sm-12">
Enter a criteria in the text box below and then click subscribe to
create a dynamic subscription and then display the results as they
arrive.
</div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#wss"
aria-controls="wss" role="tab" data-toggle="tab">Static
Websocket</a></li>
<li role="presentation"><a href="#wsd" aria-controls="wsd"
role="tab" data-toggle="tab">Dynamic Websocket</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<!-- Static Websocket -->
<div role="tabpanel" class="tab-pane active" id="wss">
<table class="table table-striped table-condensed">
<tr>
<td>ID</td>
<td>Criteria</td>
<td>Type</td>
<td>Status</td>
<td></td>
</tr>
<tr th:each="subscription : ${subscriptions}">
<td><a th:href="${subscription.id}" th:text="${subscription.id.toUnqualifiedVersionless().getIdPart()}"/>
</td>
<td th:text="${subscription.criteria}" style="max-width: 200px;"/>
<td th:text="${subscription.channel.type}" />
<td th:text="${subscription.status}" />
<td>
<button th:if="${subscription.channel.type} == 'websocket' AND ${subscription.status} == 'active'" type="button" class="btn btn-default btn-primary btn-block" id="dws_create" th:onclick="'dwsCreate(\'' + ${subscription.id.getIdPart()} + '\');'"> <i class="glyphicon glyphicon-cog"></i> Subscribe</button>
</td>
</tr>
</table>
<p th:if="${subscriptions.isEmpty()}">There are
currently no subscriptions on this server.</p>
</div>
<!-- Dynamic WebSocket -->
<div role="tabpanel" class="tab-pane" id="wsd">
<div class="row">
<div class="col-sm-12">Enter a criteria in the text box
below and then click subscribe to create a dynamic
subscription and then display the results as they arrive.</div>
</div>
<div class="row" style="boorder-top: 10px;">
<div class="col-sm-7">
<div class="input-group">
<div class="input-group-addon">Criteria</div>
<input class="form-control"
placeholder="e.g: Observation?patient=123" id="dws_criteria" />
</div>
<div class="row" style="boorder-top: 10px;">
<div class="col-sm-7">
<div class="input-group">
<div class="input-group-addon">
Criteria
</div>
<input class="form-control" placeholder="e.g: Observation?patient=123" id="dws_criteria"/>
</div>
</div>
<div class="col-sm-3">
<button type="button" class="btn btn-default btn-primary btn-block" id="dws_create" onclick="dwsCreate();"><i class="glyphicon glyphicon-cog"></i> Subscribe</button>
</div>
</div>
</div>
<div class="col-sm-3">
<button type="button"
class="btn btn-default btn-primary btn-block" id="dws_create"
onclick="dwsCreate(document.getElementById('dws_criteria').value, true);">
<i class="glyphicon glyphicon-cog"></i> Subscribe
</button>
</div>
</div>
<!-- Dynamic Subscription Results -->
<div class="panel panel-default">
<div class="panel-heading">Subscription Results</div>
<div class="panel-body">
<p>
This will be status...
</p>
</div>
<!-- List group -->
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</div>
</div>
<!-- Subscription Results -->
<div class="panel panel-default" style="display: none;"
id="resultsDiv">
<div class="panel-heading">Subscription Results</div>
<ul class="list-group" id="subscription_status_list">
</ul>
</div>
</div>
<script type="text/javascript">
function messageStatus(message) {
var listItem = $('<li />', {
'class' : 'list-group-item'
});
listItem.append($('<div class="glyphicon glyphicon-info-sign" style="width: 20px;"/>'));
listItem.append($('<span>' + message + '</span>'));
$('#subscription_status_list').append(listItem);
}
function messageIn(message, remainder) {
var listItem = $('<li />', {
'class' : 'list-group-item'
});
listItem.append($('<div class="glyphicon glyphicon-download" style="width: 20px;"/>'));
listItem.append($('<span>' + message + '</span>'));
if (remainder) {
listItem.append($('<p>(' + remainder + ' bytes)</p>'));
listItem.append($('<pre style="display:none;"/>').text(remainder));
}
$('#subscription_status_list').append(listItem);
}
function dwsCreate(bindArgument, dynamic) {
$('#resultsDiv').css("display", "");
$('#subscription_creation').hide();
try {
var url = "ws://fhirtest.uhn.ca/websocket/dstu2";
messageStatus("Connecting to: " + url);
var socket = new WebSocket(url);
socket.onopen = function() {
messageStatus("Connected to: " + url);
$('#subscription_status_list').append($('<li />', {
'class' : 'list-group-item'
}).append($('<div class="glyphicon glyphicon-upload" style="width: 20px;"/>')).append($('<span>bind ' + bindArgument + '</span>')));
socket.send("bind " + bindArgument);
}
// This function is called when a new message comes from the server
socket.onmessage = function(msg) {
var data = msg.data;
var remainder = null;
if (data.indexOf('\n') != -1) {
data = data.substring(0, data.indexOf('\n'));
remainder = data.substring(data.indexOf('\n') + 1);
}
messageIn(data, remainder);
}
socket.onerror = function(error) {
messageStatus("Error: " + error);
}
} catch (exception) {
messageStatus("Error: " + exception);
}
return false;
}
</script>
</div>
</div>

View File

@ -12,6 +12,9 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.IGenericClient;
@ -21,7 +24,7 @@ public class UhnFhirTestApp {
public static void main(String[] args) throws Exception {
int myPort = 8888;
String base = "http://localhost:" + myPort + "/base";
String base = "http://localhost:" + myPort + "/baseDstu2";
// new File("target/testdb").mkdirs();
System.setProperty("fhir.db.location", "./target/testdb");
@ -47,13 +50,13 @@ public class UhnFhirTestApp {
// base = "http://spark.furore.com/fhir";
if (true) {
FhirContext ctx = new FhirContext();
FhirContext ctx = FhirContext.forDstu2();
IGenericClient client = ctx.newRestfulGenericClient(base);
// client.setLogRequestAndResponse(true);
Organization o1 = new Organization();
o1.getName().setValue("Some Org");
MethodOutcome create = client.create(o1);
MethodOutcome create = client.create().resource(o1).execute();
IdDt orgId = (IdDt) create.getId();
Patient p1 = new Patient();
@ -64,11 +67,14 @@ public class UhnFhirTestApp {
TagList list = new TagList();
list.addTag("http://hl7.org/fhir/tag", "urn:happytag", "This is a happy resource");
ResourceMetadataKeyEnum.TAG_LIST.put(p1, list);
client.create(p1);
List<IResource> resources = ctx.newJsonParser().parseBundle(IOUtils.toString(UhnFhirTestApp.class.getResourceAsStream("/bundle.json"))).toListOfResources();
// client.transaction().withResources(resources).execute();
client.create().resource(p1).execute();
Subscription subs = new Subscription();
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
subs.setCriteria("Observation?");
client.create().resource(subs).execute();
// for (int i = 0; i < 1000; i++) {
//
// Patient p = (Patient) resources.get(0);
@ -78,22 +84,22 @@ public class UhnFhirTestApp {
// client.transaction(resources);
// }
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create(p1);
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create().resource(p1).execute();
client.create(p1);
client.create().resource(p1).execute();
}

View File

@ -57,7 +57,7 @@
<Embed-Dependency>*;scope=!provided|test</Embed-Dependency>
<Embed-Directory>lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
<_removeheaders>Built-By</_removeheaders>
<_removeheaders>Built-By, Include-Resource, Private-Package</_removeheaders>
<!-- <Private-Package>org.foo.myproject.*</Private-Package> <Bundle-Activator>org.foo.myproject.impl1.Activator</Bundle-Activator> -->
</instructions>
</configuration>
@ -70,6 +70,24 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<phase>integration-test</phase>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>

View File

@ -0,0 +1,26 @@
package ca.uhn.fhir.osgi;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import java.io.FileReader;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
public class ManifestIT {
/**
* See #234
*/
@Test
public void testValidateManifest() throws Exception {
FileReader r = new FileReader("./target/classes/META-INF/MANIFEST.MF");
String file = IOUtils.toString(r);
assertThat(file, not(containsString(".jar=/")));
}
}

View File

@ -178,7 +178,12 @@ public class GenericClientTest {
assertThat(extractBody(capt, count), containsString("value=\"John\""));
count++;
client.create().resource(ourCtx.newJsonParser().encodeResourceToString(p1)).execute();
String resourceAsString = ourCtx.newJsonParser().encodeResourceToString(p1);
client
.create()
.resource(resourceAsString)
.execute();
assertEquals(1, capt.getAllValues().get(count).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.JSON.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(count).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, count), containsString("[\"John\"]"));

View File

@ -69,9 +69,6 @@ import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class SearchSearchServerDstu1Test {
private static CloseableHttpClient ourClient;
@ -559,9 +556,6 @@ public class SearchSearchServerDstu1Test {
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyPatientResourceProvider implements IResourceProvider {
/**

View File

@ -54,6 +54,39 @@ public class JsonParserDstu2Test {
private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserDstu2Test.class);
@Test
public void testNamespacePreservationEncode() throws Exception {
//@formatter:off
String input = "<Patient xmlns=\"http://hl7.org/fhir\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">" +
"<text>" +
"<xhtml:div>" +
"<xhtml:img src=\"foo\"/>" +
"@fhirabend" +
"</xhtml:div>" +
"</text>" +
"</Patient>";
//@formatter:on
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, input);
String expected = "<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"><xhtml:img src=\"foo\"/>@fhirabend</xhtml:div>";
assertEquals(expected, parsed.getText().getDiv().getValueAsString());
String encoded = ourCtx.newJsonParser().encodeResourceToString(parsed);
ourLog.info(encoded);
assertThat(encoded, containsString("\"div\":\"" + expected.replace("\"", "\\\"") + "\""));
}
@Test
public void testNamespacePreservationParse() throws Exception {
String input = "{\"resourceType\":\"Patient\",\"text\":{\"div\":\"<xhtml:div xmlns:xhtml=\\\"http://www.w3.org/1999/xhtml\\\"><xhtml:img src=\\\"foo\\\"/>@fhirabend</xhtml:div>\"}}";
Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, input);
assertEquals("<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"><xhtml:img src=\"foo\"/>@fhirabend</xhtml:div>", parsed.getText().getDiv().getValueAsString());
String encoded = ourCtx.newXmlParser().encodeResourceToString(parsed);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"><text><xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"><xhtml:img src=\"foo\"/>@fhirabend</xhtml:div></text></Patient>",encoded);
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
@ -98,8 +131,10 @@ public class JsonParserDstu2Test {
assertThat(enc, Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"));
assertThat(enc, Matchers.stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],"));
assertThat(enc, containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{"
+ "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + "]" + "}"));
assertThat(enc,
containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{"
+ "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}"
+ "]" + "}"));
/*
* Now parse this back
@ -402,7 +437,8 @@ public class JsonParserDstu2Test {
ourLog.info(encoded);
assertThat(encoded, containsString("Patient"));
assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\":\"foo\",", "\"code\":\"bar\"", "\"system\":\"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\":\"" + Constants.TAG_SUBSETTED_CODE + "\","));
assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\":\"foo\",", "\"code\":\"bar\"", "\"system\":\"" + Constants.TAG_SUBSETTED_SYSTEM + "\",",
"\"code\":\"" + Constants.TAG_SUBSETTED_CODE + "\","));
assertThat(encoded, not(containsString("THE DIV")));
assertThat(encoded, containsString("family"));
assertThat(encoded, not(containsString("maritalStatus")));
@ -423,7 +459,8 @@ public class JsonParserDstu2Test {
String enc = ourCtx.newJsonParser().encodeResourceToString(pt);
ourLog.info(enc);
assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}", enc);
assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}",
enc);
}
@ -517,7 +554,7 @@ public class JsonParserDstu2Test {
assertEquals(exp, act);
}
/**
* Test for #146
*/
@ -636,9 +673,9 @@ public class JsonParserDstu2Test {
String content = IOUtils.toString(JsonParserDstu2Test.class.getResourceAsStream("/bundle-transaction2.json"));
ourCtx.newJsonParser().parseBundle(content);
ca.uhn.fhir.model.dstu2.resource.Bundle parsed = ourCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, content);
// TODO: preserve comments
}
@ -857,7 +894,7 @@ public class JsonParserDstu2Test {
assertEquals(exp, act);
}
@Test
public void testParsePatientInBundle() {

View File

@ -27,6 +27,7 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -42,6 +43,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Link;
@ -69,8 +71,11 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
public class GenericClientDstu2Test {
private static FhirContext ourCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
private int myResponseCount = 0;
@Before
public void before() {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
@ -106,6 +111,133 @@ public class GenericClientDstu2Test {
return msg;
}
@Test
public void testAcceptHeaderFetchConformance() throws Exception {
IParser p = ourCtx.newXmlParser();
Conformance conf = new Conformance();
conf.setCopyright("COPY");
final String respString = p.encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
client.fetchConformance().ofType(Conformance.class).execute();
assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
idx++;
client.fetchConformance().ofType(Conformance.class).encodedJson().execute();
assertEquals("http://example.com/fhir/metadata?_format=json", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
idx++;
client.fetchConformance().ofType(Conformance.class).encodedXml().execute();
assertEquals("http://example.com/fhir/metadata?_format=xml", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
idx++;
}
@Test
public void testAcceptHeaderPreflightConformance() throws Exception {
String methodName = "testAcceptHeaderPreflightConformance";
final IParser p = ourCtx.newXmlParser();
final Conformance conf = new Conformance();
conf.setCopyright("COPY");
final Patient patient = new Patient();
patient.addName().addFamily("FAMILY");
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myResponseCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(conf)), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(patient)), Charset.forName("UTF-8"));
}
}
});
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = ourCtx.newRestfulGenericClient("http://" + methodName + ".example.com/fhir");
Patient resp = client.read(Patient.class, new IdDt("123"));
assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue());
assertEquals("http://" + methodName + ".example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertEquals("http://" + methodName + ".example.com/fhir/Patient/123", capt.getAllValues().get(1).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
}
@Test
public void testAcceptHeaderPreflightConformancePreferJson() throws Exception {
String methodName = "testAcceptHeaderPreflightConformancePreferJson";
final IParser p = ourCtx.newXmlParser();
final Conformance conf = new Conformance();
conf.setCopyright("COPY");
final Patient patient = new Patient();
patient.addName().addFamily("FAMILY");
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myResponseCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(conf)), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(patient)), Charset.forName("UTF-8"));
}
}
});
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = ourCtx.newRestfulGenericClient("http://" + methodName + ".example.com/fhir");
client.setEncoding(EncodingEnum.JSON);
Patient resp = client.read(Patient.class, new IdDt("123"));
assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue());
assertEquals("http://" + methodName + ".example.com/fhir/metadata?_format=json", capt.getAllValues().get(0).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), not(containsString(Constants.CT_FHIR_XML)));
assertEquals("http://" + methodName + ".example.com/fhir/Patient/123?_format=json", capt.getAllValues().get(1).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), not(containsString(Constants.CT_FHIR_XML)));
}
@Test
@SuppressWarnings("deprecation")
public void testConformance() throws Exception {
@ -141,136 +273,6 @@ public class GenericClientDstu2Test {
}
@Test
public void testAcceptHeaderFetchConformance() throws Exception {
IParser p = ourCtx.newXmlParser();
Conformance conf = new Conformance();
conf.setCopyright("COPY");
final String respString = p.encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Conformance resp = (Conformance)client.fetchConformance().ofType(Conformance.class).execute();
assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
idx++;
resp = (Conformance)client.fetchConformance().ofType(Conformance.class).encodedJson().execute();
assertEquals("http://example.com/fhir/metadata?_format=json", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
idx++;
resp = (Conformance)client.fetchConformance().ofType(Conformance.class).encodedXml().execute();
assertEquals("http://example.com/fhir/metadata?_format=xml", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
idx++;
}
private int myResponseCount = 0;
@Test
public void testAcceptHeaderPreflightConformancePreferJson() throws Exception {
String methodName = "testAcceptHeaderPreflightConformancePreferJson";
final IParser p = ourCtx.newXmlParser();
final Conformance conf = new Conformance();
conf.setCopyright("COPY");
final Patient patient = new Patient();
patient.addName().addFamily("FAMILY");
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myResponseCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(conf)), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(patient)), Charset.forName("UTF-8"));
}
}
});
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = ourCtx.newRestfulGenericClient("http://"+methodName+".example.com/fhir");
client.setEncoding(EncodingEnum.JSON);
Patient resp = client.read(Patient.class, new IdDt("123"));
assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue());
assertEquals("http://"+methodName+".example.com/fhir/metadata?_format=json", capt.getAllValues().get(0).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), not(containsString(Constants.CT_FHIR_XML)));
assertEquals("http://"+methodName+".example.com/fhir/Patient/123?_format=json", capt.getAllValues().get(1).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), not(containsString(Constants.CT_FHIR_XML)));
}
@Test
public void testAcceptHeaderPreflightConformance() throws Exception {
String methodName = "testAcceptHeaderPreflightConformance";
final IParser p = ourCtx.newXmlParser();
final Conformance conf = new Conformance();
conf.setCopyright("COPY");
final Patient patient = new Patient();
patient.addName().addFamily("FAMILY");
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myResponseCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(conf)), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(patient)), Charset.forName("UTF-8"));
}
}
});
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = ourCtx.newRestfulGenericClient("http://"+methodName+".example.com/fhir");
Patient resp = client.read(Patient.class, new IdDt("123"));
assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue());
assertEquals("http://"+methodName+".example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertEquals("http://"+methodName+".example.com/fhir/Patient/123", capt.getAllValues().get(1).getURI().toASCIIString());
assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length);
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_ALL));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML));
assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON));
}
@Test
public void testCreate() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -382,44 +384,6 @@ public class GenericClientDstu2Test {
idx++;
}
@SuppressWarnings("deprecation")
@Test
public void testUpdateNonFluent() throws Exception {
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), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Patient p = new Patient();
p.addName().addFamily("FOOFAMILY");
client.update(new IdDt("Patient/123"), p);
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
client.update("123", p);
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
}
@Test
public void testCreatePrefer() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -450,7 +414,7 @@ public class GenericClientDstu2Test {
idx++;
}
@Test
public void testCreateReturningResourceBody() throws Exception {
Patient p = new Patient();
@ -535,7 +499,7 @@ public class GenericClientDstu2Test {
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
idx++;
client.delete(Patient.class, "123");
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
@ -631,7 +595,8 @@ public class GenericClientDstu2Test {
.since(new InstantDt("2001-01-02T11:22:33Z"))
.execute();
//@formatter:on
assertThat(capt.getAllValues().get(idx).getURI().toString(), either(equalTo("http://example.com/fhir/Patient/123/_history?_since=2001-01-02T11:22:33Z&_count=123")).or(equalTo("http://example.com/fhir/Patient/123/_history?_count=123&_since=2001-01-02T11:22:33Z")));
assertThat(capt.getAllValues().get(idx).getURI().toString(), either(equalTo("http://example.com/fhir/Patient/123/_history?_since=2001-01-02T11:22:33Z&_count=123"))
.or(equalTo("http://example.com/fhir/Patient/123/_history?_count=123&_since=2001-01-02T11:22:33Z")));
assertEquals(1, response.getEntry().size());
idx++;
@ -646,7 +611,7 @@ public class GenericClientDstu2Test {
assertThat(capt.getAllValues().get(idx).getURI().toString(), containsString("_since=2001-01"));
assertEquals(1, response.getEntry().size());
idx++;
}
}
@Test
public void testMetaAdd() throws Exception {
@ -684,12 +649,12 @@ public class GenericClientDstu2Test {
assertEquals("http://example.com/fhir/Patient/123/$meta-add", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals("urn:profile:out", resp.getProfile().get(0).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"meta\"/><valueMeta><profile value=\"urn:profile:in\"/></valueMeta></parameter></Parameters>", extractBody(capt, idx));
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"meta\"/><valueMeta><profile value=\"urn:profile:in\"/></valueMeta></parameter></Parameters>",
extractBody(capt, idx));
idx++;
}
@Test
public void testMetaGet() throws Exception {
IParser p = ourCtx.newXmlParser();
@ -946,9 +911,8 @@ public class GenericClientDstu2Test {
Parameters outParams = client.operation().onInstance(new IdDt("Patient", "18066")).named("$everything").withParameters(inParams).execute();
/*
* Note that the $everything operation returns a Bundle instead of a Parameters resource. The client operation
* methods return a Parameters instance however, so HAPI creates a Parameters object with a single parameter
* containing the value.
* Note that the $everything operation returns a Bundle instead of a Parameters resource. The client operation methods return a Parameters instance however, so HAPI creates a Parameters object
* with a single parameter containing the value.
*/
ca.uhn.fhir.model.dstu2.resource.Bundle responseBundle = (ca.uhn.fhir.model.dstu2.resource.Bundle) outParams.getParameter().get(0).getResource();
@ -1001,6 +965,121 @@ public class GenericClientDstu2Test {
idx++;
}
@Test
public void testOperationWithInlineParams() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters outParams = new Parameters();
outParams.addParameter().setValue(new StringDt("STRINGVALOUT1"));
outParams.addParameter().setValue(new StringDt("STRINGVALOUT2"));
final String respString = p.encodeResourceToString(outParams);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameter(Parameters.class, "name1", new StringDt("value1"))
.andParameter("name2", new StringDt("value1"))
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"name1\"/><valueString value=\"value1\"/></parameter><parameter><name value=\"name2\"/><valueString value=\"value1\"/></parameter></Parameters>",
(extractBody(capt, idx)));
idx++;
/*
* Composite type
*/
//@formatter:off
resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameter(Parameters.class, "name1", new IdentifierDt("system1", "value1"))
.andParameter("name2", new StringDt("value1"))
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"name1\"/><valueIdentifier><system value=\"system1\"/><value value=\"value1\"/></valueIdentifier></parameter><parameter><name value=\"name2\"/><valueString value=\"value1\"/></parameter></Parameters>",
(extractBody(capt, idx)));
idx++;
/*
* Resource
*/
//@formatter:off
resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameter(Parameters.class, "name1", new IdentifierDt("system1", "value1"))
.andParameter("name2", new Patient().setActive(true))
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"name1\"/><valueIdentifier><system value=\"system1\"/><value value=\"value1\"/></valueIdentifier></parameter><parameter><name value=\"name2\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><active value=\"true\"/></Patient></resource></parameter></Parameters>",
(extractBody(capt, idx)));
idx++;
}
@Test(expected = IllegalArgumentException.class)
public void testOperationWithInvalidParam() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
// Who knows what the heck this is!
IBase weirdBase = new IBase() {
private static final long serialVersionUID = 1L;
@Override
public boolean isEmpty() {
return false;
}
};
//@formatter:off
client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameter(Parameters.class, "name1", weirdBase)
.execute();
//@formatter:on
}
@Test
public void testOperationWithListOfParameterResponse() throws Exception {
IParser p = ourCtx.newXmlParser();
@ -1315,11 +1394,7 @@ public class GenericClientDstu2Test {
Patient response;
int idx = 0;
response = (Patient)client
.read()
.resource(Patient.class)
.withUrl(new IdDt("http://domain2.example.com/base/Patient/123"))
.execute();
response = (Patient) client.read().resource(Patient.class).withUrl(new IdDt("http://domain2.example.com/base/Patient/123")).execute();
assertEquals("http://domain2.example.com/base/Patient/123", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals("FAM", response.getName().get(0).getFamily().get(0).getValue());
}
@ -1369,7 +1444,7 @@ public class GenericClientDstu2Test {
assertEquals("2015-06-22T15:48:57.554-04:00", ResourceMetadataKeyEnum.UPDATED.get(response).getValueAsString());
}
@Test
public void testReadWithElementsParam() throws Exception {
String msg = "{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}";
@ -1390,7 +1465,8 @@ public class GenericClientDstu2Test {
.execute();
//@formatter:on
assertThat(capt.getValue().getURI().toString(), either(equalTo("http://example.com/fhir/Patient/123?_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient/123?_elements=identifier%2Cname")));
assertThat(capt.getValue().getURI().toString(),
either(equalTo("http://example.com/fhir/Patient/123?_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient/123?_elements=identifier%2Cname")));
assertEquals(Patient.class, response.getClass());
}
@ -1420,8 +1496,7 @@ public class GenericClientDstu2Test {
}
//@formatter:on
}
@Test
public void testReadWithSummaryParamHtml() throws Exception {
String msg = "<div>HELP IM A DIV</div>";
@ -1524,7 +1599,8 @@ public class GenericClientDstu2Test {
.execute();
//@formatter:on
assertThat(capt.getValue().getURI().toString(), either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
assertThat(capt.getValue().getURI().toString(),
either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
}
@ -1835,6 +1911,43 @@ public class GenericClientDstu2Test {
}
@SuppressWarnings("deprecation")
@Test
public void testUpdateNonFluent() throws Exception {
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), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Patient p = new Patient();
p.addName().addFamily("FOOFAMILY");
client.update(new IdDt("Patient/123"), p);
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
client.update("123", p);
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
}
@Test
public void testUpdatePrefer() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -1924,7 +2037,9 @@ public class GenericClientDstu2Test {
response = client.validate().resource(p).execute();
assertEquals("http://example.com/fhir/Patient/$validate", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", extractBody(capt, idx));
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>",
extractBody(capt, idx));
assertNotNull(response.getOperationOutcome());
assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue());
idx++;
@ -1932,7 +2047,9 @@ public class GenericClientDstu2Test {
response = client.validate().resource(ourCtx.newXmlParser().encodeResourceToString(p)).execute();
assertEquals("http://example.com/fhir/Patient/$validate?_format=xml", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", extractBody(capt, idx));
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>",
extractBody(capt, idx));
assertNotNull(response.getOperationOutcome());
assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue());
idx++;
@ -1986,7 +2103,9 @@ public class GenericClientDstu2Test {
assertEquals("http://example.com/fhir/Patient/$validate", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", extractBody(capt, idx));
assertEquals(
"<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>",
extractBody(capt, idx));
assertNotNull(response.getOperationOutcome());
assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue());
idx++;

View File

@ -46,6 +46,7 @@ import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.PortUtil;
/**
@ -78,6 +79,30 @@ public class LoggingInterceptorDstu2Test {
assertThat(captor.getValue(), StringContains.containsString("read - Patient/1"));
}
@Test
public void testException() throws Exception {
LoggingInterceptor interceptor = new LoggingInterceptor();
interceptor.setLogExceptions(true);
assertTrue(interceptor.isLogExceptions());
interceptor.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}");
assertEquals("ERROR - ${requestVerb} ${requestUrl}", interceptor.getErrorMessageFormat());
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
Logger logger = mock(Logger.class);
interceptor.setLogger(logger);
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/EX");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(logger, times(2)).info(captor.capture());
assertThat(captor.getAllValues().get(0), StringContains.containsString("read - Patient/EX"));
assertThat(captor.getAllValues().get(1), StringContains.containsString("ERROR - GET http://localhost:"+ourPort+"/Patient/EX"));
}
@Test
public void testSearch() throws Exception {
@ -242,6 +267,9 @@ public class LoggingInterceptorDstu2Test {
*/
@Read()
public Patient getResourceById(@IdParam IdDt theId) {
if (theId.getIdPart().equals("EX")) {
throw new InvalidRequestException("FOO");
}
String key = theId.getIdPart();
Patient retVal = getIdToPatient().get(key);
return retVal;

View File

@ -14,22 +14,8 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.formats.IParser;
import org.hl7.fhir.instance.formats.ParserType;
import org.hl7.fhir.instance.model.ConceptMap;
import org.hl7.fhir.instance.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.StructureDefinition;
import org.hl7.fhir.instance.model.ValueSet;
import org.hl7.fhir.instance.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.instance.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.instance.terminologies.ValueSetExpander;
import org.hl7.fhir.instance.terminologies.ValueSetExpanderFactory;
import org.hl7.fhir.instance.terminologies.ValueSetExpanderSimple;
import org.hl7.fhir.instance.utils.EOperationOutcome;
import org.hl7.fhir.instance.utils.INarrativeGenerator;
import org.hl7.fhir.instance.utils.IWorkerContext;
import org.hl7.fhir.instance.validation.IResourceValidator;
import org.hl7.fhir.instance.validation.IResourceValidator.BestPracticeWarningLevel;
import org.hl7.fhir.instance.validation.ValidationMessage;
import org.w3c.dom.Document;
@ -46,7 +32,6 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.validation.IValidationSupport.CodeValidationResult;
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
@ -151,7 +136,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
}
protected List<ValidationMessage> validate(final FhirContext theCtx, String theInput, EncodingEnum theEncoding) {
HapiWorkerContext workerContext = new HapiWorkerContext(theCtx);
HapiWorkerContext workerContext = new HapiWorkerContext(theCtx, myValidationSupport);
org.hl7.fhir.instance.validation.InstanceValidator v;
try {
@ -260,125 +245,4 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return profile;
}
private final class HapiWorkerContext implements IWorkerContext, ValueSetExpanderFactory, ValueSetExpander {
private final FhirContext myCtx;
private HapiWorkerContext(FhirContext theCtx) {
myCtx = theCtx;
}
@Override
public ValueSetExpansionComponent expandVS(ConceptSetComponent theInc) {
return myValidationSupport.expandValueSet(myCtx, theInc);
}
@Override
public ValueSetExpansionOutcome expandVS(ValueSet theSource) {
throw new UnsupportedOperationException();
}
@Override
public ValueSet fetchCodeSystem(String theSystem) {
if (myValidationSupport == null) {
return null;
} else {
return myValidationSupport.fetchCodeSystem(myCtx, theSystem);
}
}
@Override
public <T extends Resource> T fetchResource(Class<T> theClass, String theUri) throws EOperationOutcome, Exception {
if (myValidationSupport == null) {
return null;
} else {
return myValidationSupport.fetchResource(myCtx, theClass, theUri);
}
}
@Override
public INarrativeGenerator getNarrativeGenerator(String thePrefix, String theBasePath) {
throw new UnsupportedOperationException();
}
@Override
public IParser getParser(ParserType theType) {
throw new UnsupportedOperationException();
}
@Override
public IParser getParser(String theType) {
throw new UnsupportedOperationException();
}
@Override
public <T extends Resource> boolean hasResource(Class<T> theClass_, String theUri) {
throw new UnsupportedOperationException();
}
@Override
public IParser newJsonParser() {
throw new UnsupportedOperationException();
}
@Override
public IResourceValidator newValidator() throws Exception {
throw new UnsupportedOperationException();
}
@Override
public IParser newXmlParser() {
throw new UnsupportedOperationException();
}
@Override
public boolean supportsSystem(String theSystem) {
if (myValidationSupport == null) {
return false;
} else {
return myValidationSupport.isCodeSystemSupported(myCtx, theSystem);
}
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay) {
CodeValidationResult result = myValidationSupport.validateCode(myCtx, theSystem, theCode, theDisplay);
if (result == null) {
return null;
}
return new ValidationResult(result.getSeverity(), result.getMessage(), result.asConceptDefinition());
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay,
ConceptSetComponent theVsi) {
throw new UnsupportedOperationException();
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay, ValueSet theVs) {
throw new UnsupportedOperationException();
}
@Override
public ValueSetExpander getExpander() {
return this;
}
@Override
public ValueSetExpansionOutcome expand(ValueSet theSource) throws ETooCostly, Exception {
ValueSetExpander vse = new ValueSetExpanderSimple(this, this);
ValueSetExpansionOutcome vso = vse.expand(theSource);
if (vso.getError() != null) {
return null;
} else {
return vso;
}
}
@Override
public List<ConceptMap> findMapsForSource(String theUrl) {
throw new UnsupportedOperationException();
}
}
}

View File

@ -0,0 +1,144 @@
package ca.uhn.fhir.validation;
import java.util.List;
import org.hl7.fhir.instance.formats.IParser;
import org.hl7.fhir.instance.formats.ParserType;
import org.hl7.fhir.instance.model.ConceptMap;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.ValueSet;
import org.hl7.fhir.instance.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.instance.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.instance.terminologies.ValueSetExpander;
import org.hl7.fhir.instance.terminologies.ValueSetExpanderFactory;
import org.hl7.fhir.instance.terminologies.ValueSetExpanderSimple;
import org.hl7.fhir.instance.utils.EOperationOutcome;
import org.hl7.fhir.instance.utils.INarrativeGenerator;
import org.hl7.fhir.instance.utils.IWorkerContext;
import org.hl7.fhir.instance.validation.IResourceValidator;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.validation.IValidationSupport.CodeValidationResult;
public final class HapiWorkerContext implements IWorkerContext, ValueSetExpanderFactory, ValueSetExpander {
private final FhirContext myCtx;
private IValidationSupport myValidationSupport;
public HapiWorkerContext(FhirContext theCtx, IValidationSupport theValidationSupport) {
myCtx = theCtx;
myValidationSupport = theValidationSupport;
}
@Override
public ValueSetExpansionComponent expandVS(ConceptSetComponent theInc) {
return myValidationSupport.expandValueSet(myCtx, theInc);
}
@Override
public ValueSetExpansionOutcome expandVS(ValueSet theSource) {
throw new UnsupportedOperationException();
}
@Override
public ValueSet fetchCodeSystem(String theSystem) {
if (myValidationSupport == null) {
return null;
} else {
return myValidationSupport.fetchCodeSystem(myCtx, theSystem);
}
}
@Override
public <T extends Resource> T fetchResource(Class<T> theClass, String theUri) throws EOperationOutcome, Exception {
if (myValidationSupport == null) {
return null;
} else {
return myValidationSupport.fetchResource(myCtx, theClass, theUri);
}
}
@Override
public INarrativeGenerator getNarrativeGenerator(String thePrefix, String theBasePath) {
throw new UnsupportedOperationException();
}
@Override
public IParser getParser(ParserType theType) {
throw new UnsupportedOperationException();
}
@Override
public IParser getParser(String theType) {
throw new UnsupportedOperationException();
}
@Override
public <T extends Resource> boolean hasResource(Class<T> theClass_, String theUri) {
throw new UnsupportedOperationException();
}
@Override
public IParser newJsonParser() {
throw new UnsupportedOperationException();
}
@Override
public IResourceValidator newValidator() throws Exception {
throw new UnsupportedOperationException();
}
@Override
public IParser newXmlParser() {
throw new UnsupportedOperationException();
}
@Override
public boolean supportsSystem(String theSystem) {
if (myValidationSupport == null) {
return false;
} else {
return myValidationSupport.isCodeSystemSupported(myCtx, theSystem);
}
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay) {
CodeValidationResult result = myValidationSupport.validateCode(myCtx, theSystem, theCode, theDisplay);
if (result == null) {
return null;
}
return new ValidationResult(result.getSeverity(), result.getMessage(), result.asConceptDefinition());
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay,
ConceptSetComponent theVsi) {
throw new UnsupportedOperationException();
}
@Override
public ValidationResult validateCode(String theSystem, String theCode, String theDisplay, ValueSet theVs) {
throw new UnsupportedOperationException();
}
@Override
public ValueSetExpander getExpander() {
return this;
}
@Override
public ValueSetExpansionOutcome expand(ValueSet theSource) throws ETooCostly, Exception {
ValueSetExpander vse = new ValueSetExpanderSimple(this, this);
ValueSetExpansionOutcome vso = vse.expand(theSource);
if (vso.getError() != null) {
return null;
} else {
return vso;
}
}
@Override
public List<ConceptMap> findMapsForSource(String theUrl) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,35 @@
package ca.uhn.fhir.tinder;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import ca.uhn.fhir.tinder.parser.CompartmentParser;
public class CompartmentGeneratorMojo extends AbstractMojo {
@Parameter(required = true)
private String fhirVersion;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
CompartmentParser p = new CompartmentParser(fhirVersion);
try {
p.parse();
} catch (MojoExecutionException e) {
throw e;
} catch (MojoFailureException e) {
throw e;
} catch (Exception e) {
throw new MojoFailureException("Failure during parse", e);
}
}
public static void main(String[] args) throws MojoExecutionException, MojoFailureException {
CompartmentGeneratorMojo mojo = new CompartmentGeneratorMojo();
mojo.fhirVersion = "dstu2";
mojo.execute();
}
}

View File

@ -0,0 +1,55 @@
package ca.uhn.fhir.tinder.model;
import java.util.ArrayList;
import java.util.List;
public class CompartmentDef {
private String myOwnerResourceName;
private List<Target> myTargets;
public String getOwnerResourceName() {
return myOwnerResourceName;
}
public List<Target> getTargets() {
if (myTargets == null) {
myTargets = new ArrayList<Target>();
}
return myTargets;
}
public void setOwnerResourceName(String theOwnerResourceName) {
myOwnerResourceName = theOwnerResourceName;
}
public void setTargets(List<Target> theTargets) {
myTargets = theTargets;
}
public class Target {
private List<String> myPaths;
private String myResourceName;
public List<String> getPaths() {
if (myPaths == null) {
myPaths = new ArrayList<String>();
}
return myPaths;
}
public String getResourceName() {
return myResourceName;
}
public void setPaths(List<String> thePaths) {
myPaths = thePaths;
}
public void setResourceName(String theResourceName) {
myResourceName = theResourceName;
}
}
}

View File

@ -0,0 +1,50 @@
package ca.uhn.fhir.tinder.parser;
import java.io.InputStream;
import org.apache.maven.plugin.MojoFailureException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import ca.uhn.fhir.tinder.util.XMLUtils;
public class CompartmentParser {
private String myVersion;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CompartmentParser.class);
public CompartmentParser(String theVersion) {
myVersion = theVersion;
}
public void parse() throws Exception {
String resName = "/compartment/" + myVersion + "/compartments.xml";
InputStream nextRes = getClass().getResourceAsStream(resName);
if (nextRes == null) {
throw new MojoFailureException("Unknown base resource name: " + resName);
}
ourLog.info("Reading spreadsheet file {}", resName);
Document file;
try {
file = XMLUtils.parse(nextRes, false);
} catch (Exception e) {
throw new Exception("Failed during reading: " + resName, e);
}
Element resourcesSheet = null;
for (int i = 0; i < file.getElementsByTagName("Worksheet").getLength() && resourcesSheet == null; i++) {
resourcesSheet = (Element) file.getElementsByTagName("Worksheet").item(i);
if (!"resources".equals(resourcesSheet.getAttributeNS("urn:schemas-microsoft-com:office:spreadsheet", "Name"))) {
resourcesSheet = null;
}
}
if (resourcesSheet == null) {
throw new Exception("Failed to find worksheet with name 'Data Elements' in spreadsheet: " + resName);
}
}
}

View File

@ -0,0 +1,636 @@
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Grahame</Author>
<LastAuthor>Eric Haas</LastAuthor>
<Created>2013-07-04T21:40:46Z</Created>
<LastSaved>2015-04-10T01:54:05Z</LastSaved>
<Version>15.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>8400</WindowHeight>
<WindowWidth>19170</WindowWidth>
<WindowTopX>0</WindowTopX>
<WindowTopY>0</WindowTopY>
<ActiveSheet>1</ActiveSheet>
<RefModeR1C1/>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s62">
<Alignment ss:Horizontal="Left" ss:Vertical="Top"/>
</Style>
<Style ss:ID="s63">
<Alignment ss:Horizontal="Left" ss:Vertical="Top"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"
ss:Bold="1"/>
<Interior ss:Color="#FFFFFF" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s64">
<Alignment ss:Horizontal="Left" ss:Vertical="Top" ss:WrapText="1"/>
</Style>
<Style ss:ID="s65">
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"
ss:Bold="1"/>
<Interior ss:Color="#FFFFFF" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s66">
<Font ss:FontName="Verdana" x:Family="Swiss" ss:Size="9" ss:Color="#333333"/>
</Style>
</Styles>
<Worksheet ss:Name="compartments">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="6" x:FullColumns="1"
x:FullRows="1" ss:StyleID="s62" ss:DefaultColumnWidth="65.25"
ss:DefaultRowHeight="15">
<Column ss:StyleID="s62" ss:AutoFitWidth="0" ss:Width="108.75" ss:Span="1"/>
<Column ss:Index="3" ss:StyleID="s62" ss:AutoFitWidth="0" ss:Width="129.75"/>
<Column ss:StyleID="s62" ss:AutoFitWidth="0" ss:Width="207.75"/>
<Column ss:StyleID="s62" ss:AutoFitWidth="0" ss:Width="254.25"/>
<Row ss:AutoFitHeight="0" ss:StyleID="s63">
<Cell><Data ss:Type="String">Name</Data></Cell>
<Cell><Data ss:Type="String">Title</Data></Cell>
<Cell><Data ss:Type="String">Description</Data></Cell>
<Cell><Data ss:Type="String">Identification</Data></Cell>
<Cell><Data ss:Type="String">Inclusion</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0" ss:Height="75">
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell><Data ss:Type="String">Patient</Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The set of resources associated with a particular patient</Data></Cell>
<Cell><Data ss:Type="String">There is an instance of the patient compartment for each patient resource, and the identity of the compartment is the same as the patient. When a patient is linked to another patient, all the records associated with the linked patient are in the compartment associated with the target of the link. </Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The patient compartment includes any resources where the subject of the resource is the patient, and some other resources that are directly linked to resources in the patient compartment</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">Encounter</Data></Cell>
<Cell><Data ss:Type="String">The set of resources associated with a particular encounter</Data></Cell>
<Cell><Data ss:Type="String">There is an instance of the encounter compartment for each encounter resource, and the identity of the compartment is the same as the encounter</Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The encounter compartment includes any resources where the resource has an explicitly nominated encounter, and some other resources that them selves link to resources in the encounter compartment. Note that for many resources, the exact nature of the link to encounter can be ambiguous (e.g. for a DiagnosticReport, is it the encounter when it was initiated, or when it was reported?)</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">relatedPerson</Data></Cell>
<Cell><Data ss:Type="String">RelatedPerson</Data></Cell>
<Cell><Data ss:Type="String">The set of resources associated with a particular 'related person'</Data></Cell>
<Cell><Data ss:Type="String">There is an instance of the relatedPerson compartment for each relatedPerson resource, and the identity of the compartment is the same as the relatedPerson</Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The relatedPerson compartment includes any resources where the resource is explicitly linked to relatedPerson (usually as author)</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">practitioner</Data></Cell>
<Cell><Data ss:Type="String">Practitioner</Data></Cell>
<Cell><Data ss:Type="String">The set of resources associated with a particular practitioner</Data></Cell>
<Cell><Data ss:Type="String">There is an instance of the practitioner compartment for each Practitioner resource, and the identity of the compartment is the same as the Practitioner</Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The practitioner compartment includes any resources where the resource is explicitly linked to a Practitioner (usually as author, but other kinds of linkage exist)</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">device</Data></Cell>
<Cell><Data ss:Type="String">Device</Data></Cell>
<Cell><Data ss:Type="String">The set of resources associated with a particular device</Data></Cell>
<Cell><Data ss:Type="String">There is an instance of the practitioner compartment for each Device resource, and the identity of the compartment is the same as the Device</Data></Cell>
<Cell ss:StyleID="s64"><Data ss:Type="String">The device compartment includes any resources where the resource is explicitly linked to a Device (mostly subject or performer)</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Unsynced/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>4</ActiveRow>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<x:PageLayoutZoom>0</x:PageLayoutZoom>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="resources">
<Table ss:ExpandedColumnCount="6" ss:ExpandedRowCount="94" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="65.25" ss:DefaultRowHeight="15">
<Column ss:AutoFitWidth="0" ss:Width="156.75"/>
<Column ss:AutoFitWidth="0" ss:Width="198"/>
<Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="96"/>
<Row ss:AutoFitHeight="0" ss:StyleID="s65">
<Cell><Data ss:Type="String">Resource</Data></Cell>
<Cell><Data ss:Type="String">Patient</Data></Cell>
<Cell><Data ss:Type="String">Encounter</Data></Cell>
<Cell><Data ss:Type="String">RelatedPerson</Data></Cell>
<Cell><Data ss:Type="String">Practitioner</Data></Cell>
<Cell><Data ss:Type="String">Device</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">AllergyIntolerance</Data></Cell>
<Cell><Data ss:Type="String">patient | recorder | reporter</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">reporter</Data></Cell>
<Cell><Data ss:Type="String">recorder | reporter</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Account</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">subject</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Appointment</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">AppointmentResponse</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">AuditEvent</Data></Cell>
<Cell><Data ss:Type="String">patient | participant.patient | reference.patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">participant</Data></Cell>
<Cell><Data ss:Type="String">participant</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Basic</Data></Cell>
<Cell><Data ss:Type="String">patient | author</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Binary</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">BodySite</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Bundle</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">CarePlan</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">patient | participant | performer</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">participant | performer</Data></Cell>
<Cell><Data ss:Type="String">participant | performer</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Claim</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">provider</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ClaimResponse</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ClinicalImpression</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">assessor</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Communication</Data></Cell>
<Cell><Data ss:Type="String">subject | sender | recipient</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">CommunicationRequest</Data></Cell>
<Cell><Data ss:Type="String">subject | sender | recipient | requester</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient | requester</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient | requester</Data></Cell>
<Cell><Data ss:Type="String">sender | recipient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Composition</Data></Cell>
<Cell><Data ss:Type="String">subject | author | attester</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">subject | author | attester</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ConceptMap</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Condition</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">asserter</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Conformance</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DetectedIssue</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Contract</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Coverage</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DataElement</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Device</Data></Cell>
<Cell ss:Index="6"><Data ss:Type="String">{def}</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DeviceComponent</Data></Cell>
<Cell ss:Index="6"><Data ss:Type="String">source</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DeviceMetric</Data></Cell>
<Cell ss:Index="6"><Data ss:Type="String">source</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DeviceUseRequest</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="6"><Data ss:Type="String">device</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DeviceUseStatement</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="6"><Data ss:Type="String">device</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DiagnosticOrder</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">actor | orderer</Data></Cell>
<Cell><Data ss:Type="String">actor | subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DiagnosticReport</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">performer</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DocumentManifest</Data></Cell>
<Cell><Data ss:Type="String">subject | author | recipient</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">subject | author | recipient</Data></Cell>
<Cell><Data ss:Type="String">subject | author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">DocumentReference</Data></Cell>
<Cell><Data ss:Type="String">subject | author</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">subject | author | authenticator</Data></Cell>
<Cell><Data ss:Type="String">subject | author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">EligibilityRequest</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">EligibilityResponse</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Encounter</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell><Data ss:Type="String">{def}</Data></Cell>
<Cell><Data ss:Type="String">participant</Data></Cell>
<Cell><Data ss:Type="String">practitioner | participant</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">EnrollmentRequest</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">EnrollmentResponse</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">EpisodeOfCare</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s66"><Data ss:Type="String">care-manager | team-member</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ExplanationOfBenefit</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">FamilyMemberHistory</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Flag</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Goal</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Group</Data></Cell>
<Cell><Data ss:Type="String">member</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">member</Data></Cell>
<Cell><Data ss:Type="String">member</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">HealthcareService</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ImagingObjectSelection</Data></Cell>
<Cell><Data ss:Type="String">patient | author</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ImagingStudy</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Immunization</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">performer | requester</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ImmunizationRecommendation</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ImplementationGuide</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">List</Data></Cell>
<Cell><Data ss:Type="String">subject | source</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">source</Data></Cell>
<Cell><Data ss:Type="String">subject | source</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Location</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Media</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">subject | operator</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Medication</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">MedicationAdministration</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">practitioner</Data></Cell>
<Cell><Data ss:Type="String">device</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">MedicationDispense</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">dispenser | receiver | responsibleparty</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">MedicationOrder</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">prescriber</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">MedicationStatement</Data></Cell>
<Cell><Data ss:Type="String">patient | source</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">source</Data></Cell>
<Cell><Data ss:Type="String">source</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">MessageHeader</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">receiver | author | responsible | enterer</Data></Cell>
<Cell><Data ss:Type="String">target</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">NamingSystem</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">NutritionOrder</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">provider</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Observation</Data></Cell>
<Cell><Data ss:Type="String">subject | performer</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">performer</Data></Cell>
<Cell><Data ss:Type="String">performer</Data></Cell>
<Cell><Data ss:Type="String">subject | device</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">OperationDefinition</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">OperationOutcome</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Order</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">source | target</Data></Cell>
<Cell><Data ss:Type="String">target</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">OrderResponse</Data></Cell>
<Cell><Data ss:Type="String">request.patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">who</Data></Cell>
<Cell><Data ss:Type="String">who</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Organization</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Patient</Data></Cell>
<Cell><Data ss:Type="String">link</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s66"><Data ss:Type="String">careprovider</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">PaymentNotice</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">PaymentReconciliation</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Person</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">link</Data></Cell>
<Cell><Data ss:Type="String">practitioner</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Practitioner</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">{def}</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Procedure</Data></Cell>
<Cell><Data ss:Type="String">patient | performer</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">performer</Data></Cell>
<Cell><Data ss:Type="String">performer</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ProcedureRequest</Data></Cell>
<Cell><Data ss:Type="String">subject | orderer | performer</Data></Cell>
<Cell><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">performer | orderer</Data></Cell>
<Cell><Data ss:Type="String">performer | orderer</Data></Cell>
<Cell><Data ss:Type="String">orderer</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ProcessRequest</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">provider</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ProcessResponse</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">requestprovider</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Provenance</Data></Cell>
<Cell><Data ss:Type="String">target.subject | target.patient | patient</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">agent</Data></Cell>
<Cell><Data ss:Type="String">agent</Data></Cell>
<Cell><Data ss:Type="String">agent</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Questionnaire</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">QuestionnaireResponse</Data></Cell>
<Cell><Data ss:Type="String">subject | author</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">encounter</Data></Cell>
<Cell><Data ss:Type="String">author | source</Data></Cell>
<Cell><Data ss:Type="String">author | source</Data></Cell>
<Cell><Data ss:Type="String">author</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ReferralRequest</Data></Cell>
<Cell><Data ss:Type="String">patient | requester</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">requester | recipient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">RelatedPerson</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">{def}</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">RiskAssessment</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">performer</Data></Cell>
<Cell><Data ss:Type="String">performer</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Schedule</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell ss:Index="4"><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
<Cell><Data ss:Type="String">actor</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">SearchParameter</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Slot</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Specimen</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">collector</Data></Cell>
<Cell><Data ss:Type="String">subject</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">StructureDefinition</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Subscription</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">Substance</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0" ss:Height="15.75">
<Cell><Data ss:Type="String">SupplyRequest</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0" ss:Height="15.75">
<Cell><Data ss:Type="String">SupplyDelivery</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">supplier | receiver</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">TestScript</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">ValueSet</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">VisionPrescription</Data></Cell>
<Cell><Data ss:Type="String">patient</Data></Cell>
<Cell ss:StyleID="s66"><Data ss:Type="String">encounter</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">prescriber</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Unsynced/>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>600</VerticalResolution>
</Print>
<Selected/>
<FreezePanes/>
<FrozenNoSplit/>
<SplitHorizontal>1</SplitHorizontal>
<TopRowBottomPane>10</TopRowBottomPane>
<ActivePane>2</ActivePane>
<Panes>
<Pane>
<Number>3</Number>
</Pane>
<Pane>
<Number>2</Number>
<ActiveRow>20</ActiveRow>
<RangeSelection>R21</RangeSelection>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<x:PageLayoutZoom>0</x:PageLayoutZoom>
</WorksheetOptions>
</Worksheet>
</Workbook>

View File

@ -15,6 +15,7 @@
<bean id="myFhirContext${versionCapitalized}" class="ca.uhn.fhir.context.FhirContext" factory-method="for${versionCapitalized}"/>
<bean id="mySystemDao${versionCapitalized}" class="ca.uhn.fhir.jpa.dao.FhirSystemDao${versionCapitalized}">
<property name="context" ref="myFhirContext${versionCapitalized}"/>
</bean>
@ -23,6 +24,7 @@
</bean>
#if ( ${versionCapitalized} == 'Dstu2' )
<bean id="myFhirContextDstu2Hl7Org" class="ca.uhn.fhir.context.FhirContext" factory-method="forDstu2Hl7Org"/>
<jpa:repositories base-package="ca.uhn.fhir.jpa.dao.data" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
@ -41,7 +43,7 @@
#foreach ( $res in $resources )
<bean id="my${res.name}Dao${versionCapitalized}"
## Some resource types have customized DAOs for resource specific functionality
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'ValueSet'))
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'ValueSet'))
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${res.name}${versionCapitalized}">
#else
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">

View File

@ -186,6 +186,10 @@
<id>SingingTree</id>
<name>Bryce Van Dyk</name>
</developer>
<developer>
<id>botunge</id>
<name>Thomas Andersen</name>
</developer>
</developers>
<licenses>

View File

@ -106,6 +106,39 @@
did not have latest valueset definitions applied. Thanks
to Bill de Beaubien for reporting!
</action>
<action type="fix">
JPA server can now successfully search for tokens pointing at code values
(values with no explicit system but an implied one, such as Patient.gender)
even if the system is supplied in the query.
</action>
<action type="fix" issue="235">
Correct issues with Android library. Thanks to
Thomas Andersen for the submission!
</action>
<action type="fix">
JPA server incorrectly rejected match URLs
if they did not contain a question mark. Thanks
to Bill de Beaubien for reporting!
</action>
<action type="fix" issue="234">
Remove invalid entries in OSGi Manifest. Thanks
to Alexander Kley for the fix!
</action>
<action type="add">
JPA server now supports $everything on Patient and Encounter types (patient and encounter instance was already supported)
</action>
<action type="add">
Generic client operation invocations now
have an additional inline method for generating the input
Parameters using chained method calls instead
of by passing a Parameters resource in
</action>
<action type="fix">
Parsing an XML resource where the XHTML
namespace was declared before the beginning
of the narrative section caused an invalid
re-encoding when encoding to JSON.
</action>
</release>
<release version="1.2" date="2015-09-18">
<action type="add">

View File

@ -8,6 +8,8 @@ for i in $(find $FHIRTRUNK/build/source -name *-spreadsheet.xml | egrep "/[a-z0-
rm hapi-tinder-plugin/src/main/resources/dt/dstu2/*
for i in $(find $FHIRTRUNK/build/source/datatypes | grep xml | grep -v spreadsheet | grep -v -); do cp -v $i hapi-tinder-plugin/src/main/resources/dt/dstu2/; done
cp ~/workspace/fhir/trunk/build/source/compartments.xml hapi-tinder-plugin/src/main/resources/compartment/
cp $FHIRTRUNK/build/publish/valuesets.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/
cp $FHIRTRUNK/build/publish/v3-codesystems.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/
cp $FHIRTRUNK/build/publish/v2-codesystems.xml hapi-fhir-validation-resources/src/main/resources/org/hl7/fhir/instance/model/valueset/