Merge branch 'master' of https://github.com/jamesagnew/hapi-fhir
This commit is contained in:
commit
fb80c79103
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.java]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
|
@ -47,7 +47,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>2.1-SNAPSHOT</version>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
|
|
@ -60,6 +60,11 @@ public class PagingPatientProvider implements IResourceProvider {
|
|||
// Typically this method just returns null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1889,7 +1889,11 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
for (Include next : myRevInclude) {
|
||||
addParam(params, Constants.PARAM_REVINCLUDE, next.getValue());
|
||||
if (next.isRecurse()) {
|
||||
addParam(params, Constants.PARAM_REVINCLUDE_RECURSE, next.getValue());
|
||||
} else {
|
||||
addParam(params, Constants.PARAM_REVINCLUDE, next.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2)) {
|
||||
|
|
|
@ -171,7 +171,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return new IBundleProvider() {
|
||||
|
||||
@Override
|
||||
public InstantDt getPublished() {
|
||||
public IPrimitiveType<Date> getPublished() {
|
||||
return resources.getPublished();
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,12 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
@Override
|
||||
public Integer preferredPageSize() {
|
||||
return null;
|
||||
return resources.preferredPageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return resources.getUuid();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -48,7 +48,7 @@ abstract class BaseParam implements IQueryParameterType {
|
|||
public Boolean getMissing() {
|
||||
return myMissing;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final String getQueryParameterQualifier() {
|
||||
if (myMissing != null && myMissing.booleanValue()) {
|
||||
|
@ -73,8 +73,8 @@ abstract class BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
/**
|
||||
* If set to non-null value, indicates that this parameter has been populated
|
||||
* with a "[name]:missing=true" or "[name]:missing=false" vale instead of a
|
||||
* If set to non-null value, indicates that this parameter has been populated
|
||||
* with a "[name]:missing=true" or "[name]:missing=false" vale instead of a
|
||||
* normal value
|
||||
*
|
||||
* @return Returns a reference to <code>this</code> for easier method chaining
|
||||
|
@ -97,10 +97,10 @@ abstract class BaseParam implements IQueryParameterType {
|
|||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
myMissing = null;
|
||||
doSetValueAsQueryToken(theContext, theParamName, theQualifier, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.param;
|
|||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
|
@ -32,17 +33,26 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
|
||||
public class StringParam extends BaseParam implements IQueryParameterType {
|
||||
|
||||
private boolean myContains;
|
||||
private boolean myExact;
|
||||
private String myValue;
|
||||
private boolean myContains;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public StringParam() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public StringParam(String theValue) {
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public StringParam(String theValue, boolean theExact) {
|
||||
setValue(theValue);
|
||||
setExact(theExact);
|
||||
|
@ -79,6 +89,29 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof StringParam)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StringParam other = (StringParam) obj;
|
||||
|
||||
EqualsBuilder eb = new EqualsBuilder();
|
||||
eb.append(myExact, other.myExact);
|
||||
eb.append(myContains, other.myContains);
|
||||
eb.append(myValue, other.myValue);
|
||||
eb.append(getMissing(), other.getMissing());
|
||||
|
||||
return eb.isEquals();
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
@ -91,6 +124,13 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return defaultString(myValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* String parameter modifier <code>:contains</code>
|
||||
*/
|
||||
public boolean isContains() {
|
||||
return myContains;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return StringUtils.isEmpty(myValue);
|
||||
}
|
||||
|
@ -99,6 +139,18 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return myExact;
|
||||
}
|
||||
|
||||
/**
|
||||
* String parameter modifier <code>:contains</code>
|
||||
*/
|
||||
public StringParam setContains(boolean theContains) {
|
||||
myContains = theContains;
|
||||
if (myContains) {
|
||||
setExact(false);
|
||||
setMissing(null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringParam setExact(boolean theExact) {
|
||||
myExact = theExact;
|
||||
if (myExact) {
|
||||
|
@ -108,13 +160,6 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String parameter modifier <code>:contains</code>
|
||||
*/
|
||||
public boolean isContains() {
|
||||
return myContains;
|
||||
}
|
||||
|
||||
public StringParam setValue(String theValue) {
|
||||
myValue = theValue;
|
||||
return this;
|
||||
|
@ -136,16 +181,4 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* String parameter modifier <code>:contains</code>
|
||||
*/
|
||||
public StringParam setContains(boolean theContains) {
|
||||
myContains = theContains;
|
||||
if (myContains) {
|
||||
setExact(false);
|
||||
setMissing(null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public abstract class BasePagingProvider implements IPagingProvider {
|
||||
|
||||
private int myDefaultPageSize = 10;
|
||||
private int myMaximumPageSize = 50;
|
||||
|
||||
public BasePagingProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultPageSize() {
|
||||
return myDefaultPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumPageSize() {
|
||||
return myMaximumPageSize;
|
||||
}
|
||||
|
||||
public BasePagingProvider setDefaultPageSize(int theDefaultPageSize) {
|
||||
Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0");
|
||||
myDefaultPageSize = theDefaultPageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BasePagingProvider setMaximumPageSize(int theMaximumPageSize) {
|
||||
Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0");
|
||||
myMaximumPageSize = theMaximumPageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -64,6 +64,11 @@ public class BundleProviders {
|
|||
public Integer preferredPageSize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -40,11 +40,13 @@ public class Constants {
|
|||
public static final String CT_HTML = "text/html";
|
||||
public static final String CT_HTML_WITH_UTF8 = "text/html" + CHARSET_UTF8_CTSUFFIX;
|
||||
public static final String CT_JSON = "application/json";
|
||||
public static final String CT_JSON_PATCH = "application/json-patch+json";
|
||||
public static final String CT_OCTET_STREAM = "application/octet-stream";
|
||||
public static final String CT_TEXT = "text/plain";
|
||||
public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + CHARSET_UTF8_CTSUFFIX;
|
||||
public static final String CT_X_FORM_URLENCODED = "application/x-www-form-urlencoded";
|
||||
public static final String CT_XML = "application/xml";
|
||||
public static final String CT_XML_PATCH = "application/xml-patch+xml";
|
||||
public static final String ENCODING_GZIP = "gzip";
|
||||
public static final String EXTOP_VALIDATE = "$validate";
|
||||
public static final String EXTOP_VALIDATE_MODE = "mode";
|
||||
|
@ -61,10 +63,10 @@ public class Constants {
|
|||
public static final String FORMATS_HTML_XML = "html/xml";
|
||||
public static final String HEADER_ACCEPT = "Accept";
|
||||
public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
|
||||
public static final String HEADER_ACCEPT_VALUE_JSON_NON_LEGACY = CT_FHIR_JSON_NEW + ";q=1.0, " + CT_FHIR_JSON + ";q=0.9";
|
||||
public static final String HEADER_ACCEPT_VALUE_XML_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_XML + ";q=0.9";
|
||||
public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0";
|
||||
public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_JSON_NEW + ";q=1.0, " + HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY.replace("1.0", "0.9");
|
||||
public static final String HEADER_ACCEPT_VALUE_XML_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_XML + ";q=0.9";
|
||||
public static final String HEADER_ACCEPT_VALUE_JSON_NON_LEGACY = CT_FHIR_JSON_NEW + ";q=1.0, " + CT_FHIR_JSON + ";q=0.9";
|
||||
public static final String HEADER_ALLOW = "Allow";
|
||||
public static final String HEADER_AUTHORIZATION = "Authorization";
|
||||
public static final String HEADER_AUTHORIZATION_VALPREFIX_BASIC = "Basic ";
|
||||
|
@ -127,10 +129,12 @@ public class Constants {
|
|||
public static final String PARAM_PAGINGACTION = "_getpages";
|
||||
public static final String PARAM_PAGINGOFFSET = "_getpagesoffset";
|
||||
public static final String PARAM_PRETTY = "_pretty";
|
||||
public static final String PARAM_PRETTY_VALUE_FALSE = "false";
|
||||
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
|
||||
public static final String PARAM_PROFILE = "_profile";
|
||||
public static final String PARAM_QUERY = "_query";
|
||||
public static final String PARAM_REVINCLUDE = "_revinclude";
|
||||
public static final String PARAM_REVINCLUDE_RECURSE = PARAM_REVINCLUDE+PARAM_INCLUDE_QUALIFIER_RECURSE;
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String PARAM_SECURITY = "_security";
|
||||
public static final String PARAM_SINCE = "_since";
|
||||
|
@ -156,11 +160,11 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_401_CLIENT_UNAUTHORIZED = 401;
|
||||
public static final int STATUS_HTTP_403_FORBIDDEN = 403;
|
||||
public static final int STATUS_HTTP_404_NOT_FOUND = 404;
|
||||
|
||||
public static final int STATUS_HTTP_405_METHOD_NOT_ALLOWED = 405;
|
||||
public static final int STATUS_HTTP_409_CONFLICT = 409;
|
||||
public static final int STATUS_HTTP_410_GONE = 410;
|
||||
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
||||
|
||||
public static final int STATUS_HTTP_422_UNPROCESSABLE_ENTITY = 422;
|
||||
public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
|
||||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
|
@ -168,9 +172,6 @@ public class Constants {
|
|||
public static final String TAG_SUBSETTED_SYSTEM = "http://hl7.org/fhir/v3/ObservationValue";
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String CT_JSON_PATCH = "application/json-patch+json";
|
||||
public static final String CT_XML_PATCH = "application/xml-patch+xml";
|
||||
public static final String PARAM_PRETTY_VALUE_FALSE = "false";
|
||||
|
||||
static {
|
||||
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -25,11 +25,9 @@ import java.util.UUID;
|
|||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class FifoMemoryPagingProvider implements IPagingProvider {
|
||||
public class FifoMemoryPagingProvider extends BasePagingProvider implements IPagingProvider {
|
||||
|
||||
private LinkedHashMap<String, IBundleProvider> myBundleProviders;
|
||||
private int myDefaultPageSize=10;
|
||||
private int myMaximumPageSize=50;
|
||||
private int mySize;
|
||||
|
||||
public FifoMemoryPagingProvider(int theSize) {
|
||||
|
@ -39,33 +37,11 @@ public class FifoMemoryPagingProvider implements IPagingProvider {
|
|||
myBundleProviders = new LinkedHashMap<String, IBundleProvider>(mySize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultPageSize() {
|
||||
return myDefaultPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumPageSize() {
|
||||
return myMaximumPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized IBundleProvider retrieveResultList(String theId) {
|
||||
return myBundleProviders.get(theId);
|
||||
}
|
||||
|
||||
public FifoMemoryPagingProvider setDefaultPageSize(int theDefaultPageSize) {
|
||||
Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0");
|
||||
myDefaultPageSize = theDefaultPageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FifoMemoryPagingProvider setMaximumPageSize(int theMaximumPageSize) {
|
||||
Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0");
|
||||
myMaximumPageSize = theMaximumPageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String storeResultList(IBundleProvider theList) {
|
||||
while (myBundleProviders.size() > mySize) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.server;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -23,6 +25,7 @@ package ca.uhn.fhir.rest.server;
|
|||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
||||
|
@ -31,15 +34,17 @@ public interface IBundleProvider {
|
|||
/**
|
||||
* Load the given collection of resources by index, plus any additional resources per the
|
||||
* server's processing rules (e.g. _include'd resources, OperationOutcome, etc.). For example,
|
||||
* if the method is invoked with index 0,10 the method might return 10 search results, plus an
|
||||
* if the method is invoked with index 0,10 the method might return 10 search results, plus an
|
||||
* additional 20 resources which matched a client's _include specification.
|
||||
*
|
||||
* @param theFromIndex The low index (inclusive) to return
|
||||
* @param theToIndex The high index (exclusive) to return
|
||||
* @param theFromIndex
|
||||
* The low index (inclusive) to return
|
||||
* @param theToIndex
|
||||
* The high index (exclusive) to return
|
||||
* @return A list of resources. The size of this list must be at least <code>theToIndex - theFromIndex</code>.
|
||||
*/
|
||||
List<IBaseResource> getResources(int theFromIndex, int theToIndex);
|
||||
|
||||
|
||||
/**
|
||||
* Optionally may be used to signal a preferred page size to the server, e.g. because
|
||||
* the implementing code recognizes that the resources which will be returned by this
|
||||
|
@ -50,16 +55,31 @@ public interface IBundleProvider {
|
|||
* @return Returns the preferred page size or <code>null</code>
|
||||
*/
|
||||
Integer preferredPageSize();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the total number of results which match the given query (exclusive of any
|
||||
* _include's or OperationOutcome)
|
||||
*/
|
||||
int size();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the instant as of which this result was valid
|
||||
*/
|
||||
InstantDt getPublished();
|
||||
IPrimitiveType<Date> getPublished();
|
||||
|
||||
/**
|
||||
* Returns the UUID associated with this search. Note that this
|
||||
* does not need to return a non-null value unless it a
|
||||
* {@link IPagingProvider} is being used that requires UUIDs
|
||||
* being returned.
|
||||
* <p>
|
||||
* In other words, if you are using the default {@link FifoMemoryPagingProvider} in
|
||||
* your server, it is fine for this method to simply return {@code null} since {@link FifoMemoryPagingProvider}
|
||||
* does not use the value anyhow. On the other hand, if you are creating a custom
|
||||
* [@code IPagingProvider} implementation you might use this method to communicate
|
||||
* the search ID back to the provider.
|
||||
* </p>
|
||||
*/
|
||||
public String getUuid();
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
|
|
@ -65,5 +65,10 @@ public class SimpleBundleProvider implements IBundleProvider {
|
|||
public Integer preferredPageSize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.util;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
|
@ -84,6 +85,7 @@ public class ParametersUtil {
|
|||
}
|
||||
|
||||
public static IBaseParameters newInstance(FhirContext theContext) {
|
||||
Validate.notNull(theContext, "theContext must not be null");
|
||||
return (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionEntryHasInvalidVerb=Transac
|
|||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.cantValidateWithNoResource=No resource supplied for $validate operation (resource is required unless mode is \"delete\")
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithInvalidId=Can not process entity with ID[{0}], this is not a valid FHIR ID
|
||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.incorrectResourceType=Incorrect resource type detected for endpoint, found {0} but expected {1}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class StringParamTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
StringParam input = new StringParam("foo", true);
|
||||
|
||||
assertTrue(input.equals(input));
|
||||
assertFalse(input.equals(null));
|
||||
assertFalse(input.equals(""));
|
||||
assertFalse(input.equals(new StringParam("foo", false)));
|
||||
}
|
||||
|
||||
}
|
|
@ -101,6 +101,7 @@ public class BaseDstu2Config extends BaseConfig {
|
|||
public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2 systemProviderDstu2() {
|
||||
ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2 retVal = new ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2();
|
||||
retVal.setDao(systemDaoDstu2());
|
||||
retVal.setContext(fhirContextDstu2());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -335,7 +335,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Class<? extends IBaseResource> type = resourceDefinition.getImplementingClass();
|
||||
String id = nextId.getIdPart();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
|
@ -677,18 +677,19 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
theRequestDetails.getUserData().put(PROCESSING_SUB_REQUEST, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void notifyInterceptors(RestOperationTypeEnum theOperationType, ActionRequestDetails theRequestDetails) {
|
||||
if (theRequestDetails.getId() != null && theRequestDetails.getId().hasResourceType() && isNotBlank(theRequestDetails.getResourceType())) {
|
||||
if (theRequestDetails.getId().getResourceType().equals(theRequestDetails.getResourceType()) == false) {
|
||||
throw new InternalErrorException("Inconsistent server state - Resource types don't match: " + theRequestDetails.getId().getResourceType() + " / " + theRequestDetails.getResourceType());
|
||||
throw new InternalErrorException(
|
||||
"Inconsistent server state - Resource types don't match: " + theRequestDetails.getId().getResourceType() + " / " + theRequestDetails.getResourceType());
|
||||
}
|
||||
}
|
||||
|
||||
if (theRequestDetails.getUserData().get(PROCESSING_SUB_REQUEST) == Boolean.TRUE) {
|
||||
theRequestDetails.notifyIncomingRequestPreHandled(theOperationType);
|
||||
}
|
||||
|
||||
|
||||
List<IServerInterceptor> interceptors = getConfig().getInterceptors();
|
||||
if (interceptors == null) {
|
||||
return;
|
||||
|
@ -779,7 +780,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
theEntity.setHasTags(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ArrayList<ResourceTag> existingTags = new ArrayList<ResourceTag>();
|
||||
if (theEntity.isHasTags()) {
|
||||
existingTags.addAll(theEntity.getTags());
|
||||
|
@ -937,9 +938,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
* Subclasses may override to provide behaviour. Called when a resource has been inserted into the database for the first time.
|
||||
*
|
||||
* @param theEntity
|
||||
* The entity being updated (Do not modify the entity! Undefined behaviour will occur!)
|
||||
* The entity being updated (Do not modify the entity! Undefined behaviour will occur!)
|
||||
* @param theTag
|
||||
* The tag
|
||||
* The tag
|
||||
* @return Returns <code>true</code> if the tag should be removed
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -951,9 +952,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
* Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database
|
||||
*
|
||||
* @param theEntity
|
||||
* The resource
|
||||
* The resource
|
||||
* @param theResource
|
||||
* The resource being persisted
|
||||
* The resource being persisted
|
||||
*/
|
||||
protected void postUpdate(ResourceTable theEntity, T theResource) {
|
||||
// nothing
|
||||
|
@ -1009,9 +1010,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
* </p>
|
||||
*
|
||||
* @param theEntity
|
||||
* The entity being updated (Do not modify the entity! Undefined behaviour will occur!)
|
||||
* The entity being updated (Do not modify the entity! Undefined behaviour will occur!)
|
||||
* @param theTag
|
||||
* The tag
|
||||
* The tag
|
||||
* @return Retturns <code>true</code> if the tag should be removed
|
||||
*/
|
||||
protected boolean shouldDroppedTagBeRemovedOnUpdate(ResourceTable theEntity, ResourceTag theTag) {
|
||||
|
@ -1072,7 +1073,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IParser parser = theEntity.getEncoding().newParser(getContext(theEntity.getFhirVersion()));
|
||||
R retVal;
|
||||
try {
|
||||
|
@ -1241,7 +1242,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
}
|
||||
|
||||
/*
|
||||
* Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the matching
|
||||
* Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the
|
||||
* matching
|
||||
* resource.
|
||||
*/
|
||||
if (myConfig.isAllowInlineMatchUrlReferences()) {
|
||||
|
@ -1437,7 +1439,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
theEntity.setResourceLinks(links);
|
||||
|
||||
theEntity.toString();
|
||||
|
||||
|
||||
} // if thePerformIndexing
|
||||
|
||||
theEntity = myEntityManager.merge(theEntity);
|
||||
|
@ -1538,9 +1540,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
* "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
|
||||
* The resource that is about to be persisted
|
||||
* @param theEntityToSave
|
||||
* TODO
|
||||
* TODO
|
||||
*/
|
||||
protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) {
|
||||
Object tag = null;
|
||||
|
@ -1747,7 +1749,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
paramMap.add(nextParamName, param);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (Constants.PARAM_COUNT.equals(nextParamName)) {
|
||||
if (paramList.size() > 0 && paramList.get(0).size() > 0) {
|
||||
String intString = paramList.get(0).get(0);
|
||||
|
@ -1772,7 +1774,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
} else {
|
||||
RuntimeSearchParam paramDef = theCallingDao.getSearchParamByName(resourceDef, 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);
|
||||
throw new InvalidRequestException(
|
||||
"Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(theContext, paramDef, nextParamName, paramList);
|
||||
|
|
|
@ -22,29 +22,15 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
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.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -59,42 +45,21 @@ import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
|||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.jpa.util.DeleteConflict;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils;
|
||||
import ca.uhn.fhir.jpa.util.xmlpatch.XmlPatchUtils;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.*;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.QualifierDetails;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
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.exceptions.*;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
@ -110,14 +75,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
protected IResourceTableDao myResourceTableDao;
|
||||
@Autowired
|
||||
protected PlatformTransactionManager myPlatformTransactionManager;
|
||||
@Autowired
|
||||
private IResourceHistoryTableDao myResourceHistoryTableDao;
|
||||
@Autowired()
|
||||
protected IResourceIndexedSearchParamUriDao myResourceIndexedSearchParamUriDao;
|
||||
private String myResourceName;
|
||||
@Autowired
|
||||
protected IResourceTableDao myResourceTableDao;
|
||||
private Class<T> myResourceType;
|
||||
@Autowired(required = false)
|
||||
protected IFulltextSearchSvc mySearchDao;
|
||||
|
@ -226,7 +191,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
|
||||
preDelete(resourceToDelete);
|
||||
|
||||
// Notify interceptors
|
||||
if (theRequestDetails != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
|
||||
|
@ -259,10 +226,18 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
|
||||
|
||||
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", 1, w.getMillis());
|
||||
String severity = "information";
|
||||
String code = "informational";
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
|
||||
|
||||
ourLog.info("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart());
|
||||
return toMethodOutcome(savedEntity, null);
|
||||
DaoMethodOutcome retVal = toMethodOutcome(savedEntity, null);
|
||||
retVal.setOperationOutcome(oo);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ResourceTable> deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
||||
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
||||
|
@ -301,7 +276,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome deleteByUrl(String theUrl, RequestDetails theRequestDetails) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
@ -320,7 +295,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
|
||||
} else {
|
||||
oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", theUrl, deletedResources.size(), w.getMillis());
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", deletedResources.size(), w.getMillis());
|
||||
String severity = "information";
|
||||
String code = "informational";
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
|
||||
|
@ -553,6 +528,38 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId);
|
||||
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
BaseHasResource entity = readEntity(theResourceId);
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException(theResourceId);
|
||||
}
|
||||
|
||||
ResourceTable latestVersion = readEntityLatestVersion(theResourceId);
|
||||
if (latestVersion.getVersion() != entity.getVersion()) {
|
||||
doMetaDelete(theMetaDel, entity);
|
||||
} else {
|
||||
doMetaDelete(theMetaDel, latestVersion);
|
||||
|
||||
// Also update history entry
|
||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(entity.getId(), entity.getVersion());
|
||||
doMetaDelete(theMetaDel, history);
|
||||
}
|
||||
|
||||
myEntityManager.flush();
|
||||
|
||||
ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() });
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequestDetails);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public IBundleProvider everything(IIdType theId) {
|
||||
// Search search = new Search();
|
||||
|
@ -635,38 +642,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
// };
|
||||
// }
|
||||
|
||||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) {
|
||||
// Notify interceptors
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId);
|
||||
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
BaseHasResource entity = readEntity(theResourceId);
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException(theResourceId);
|
||||
}
|
||||
|
||||
ResourceTable latestVersion = readEntityLatestVersion(theResourceId);
|
||||
if (latestVersion.getVersion() != entity.getVersion()) {
|
||||
doMetaDelete(theMetaDel, entity);
|
||||
} else {
|
||||
doMetaDelete(theMetaDel, latestVersion);
|
||||
|
||||
// Also update history entry
|
||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(entity.getId(), entity.getVersion());
|
||||
doMetaDelete(theMetaDel, history);
|
||||
}
|
||||
|
||||
myEntityManager.flush();
|
||||
|
||||
ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() });
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequestDetails);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequestDetails) {
|
||||
// Notify interceptors
|
||||
|
@ -743,6 +718,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override to provide behaviour. Invoked within a delete
|
||||
* transaction with the resource that is about to be deleted.
|
||||
*/
|
||||
protected void preDelete(T theResourceToDelete) {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* May be overridden by subclasses to validate resources prior to storage
|
||||
*
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.Tuple;
|
||||
|
@ -64,15 +65,17 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirSystemDao.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTxManager;
|
||||
|
||||
@Autowired
|
||||
private IForcedIdDao myForcedIdDao;
|
||||
|
||||
private ReentrantLock myReindexLock = new ReentrantLock(false);
|
||||
|
||||
@Autowired
|
||||
private ITermConceptDao myTermConceptDao;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTxManager;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public void deleteAllTagsOnServer(RequestDetails theRequestDetails) {
|
||||
|
@ -205,8 +208,14 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
@Transactional()
|
||||
@Override
|
||||
public int markAllResourcesForReindexing() {
|
||||
|
||||
ourLog.info("Marking all resources as needing reindexing");
|
||||
int retVal = myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " t SET t.myIndexStatus = null").executeUpdate();
|
||||
|
||||
ourLog.info("Marking all concepts as needing reindexing");
|
||||
retVal += myTermConceptDao.markAllForReindexing();
|
||||
|
||||
ourLog.info("Done marking reindexing");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -266,16 +275,21 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
public int performReindexingPass(final Integer theCount) {
|
||||
if (!myReindexLock.tryLock()) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return doPerformReindexingPass(theCount);
|
||||
} catch (ReindexFailureException e) {
|
||||
ourLog.warn("Reindexing failed for resource {}", e.getResourceId());
|
||||
markResourceAsIndexingFailed(e.getResourceId());
|
||||
return -1;
|
||||
} finally {
|
||||
myReindexLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -27,7 +27,6 @@ import java.util.Map;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
|
@ -37,8 +36,6 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
|
||||
public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
||||
|
||||
private static final Map<String, RuntimeSearchParam> EMPTY_SP_MAP = Collections.emptyMap();
|
||||
|
||||
private Map<String, Map<String, RuntimeSearchParam>> myBuiltInSearchParams;
|
||||
|
||||
@Autowired
|
||||
|
@ -56,27 +53,32 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
public Map<String, Map<String, RuntimeSearchParam>> getBuiltInSearchParams() {
|
||||
@Override
|
||||
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
|
||||
return myBuiltInSearchParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||
Validate.notBlank(theResourceName, "theResourceName must not be blank or null");
|
||||
|
||||
return myBuiltInSearchParams.get(theResourceName);
|
||||
}
|
||||
|
||||
public Map<String, Map<String, RuntimeSearchParam>> getBuiltInSearchParams() {
|
||||
return myBuiltInSearchParams;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<String, Map<String,RuntimeSearchParam>>();
|
||||
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<String, Map<String, RuntimeSearchParam>>();
|
||||
|
||||
for (IFhirResourceDao<?> nextDao : myDaos) {
|
||||
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType());
|
||||
String nextResourceName = nextResDef.getName();
|
||||
HashMap<String, RuntimeSearchParam> nameToParam = new HashMap<String, RuntimeSearchParam>();
|
||||
resourceNameToSearchParams.put(nextResourceName, nameToParam);
|
||||
|
||||
|
||||
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
|
||||
nameToParam.put(nextSp.getName(), nextSp);
|
||||
}
|
||||
|
@ -85,13 +87,4 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
|||
myBuiltInSearchParams = Collections.unmodifiableMap(resourceNameToSearchParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
||||
Validate.notBlank(theResourceName, "theResourceName must not be null or blank");
|
||||
|
||||
Map<String, RuntimeSearchParam> map = myBuiltInSearchParams.get(theResourceName);
|
||||
map = ObjectUtils.defaultIfNull(map, EMPTY_SP_MAP);
|
||||
return Collections.unmodifiableCollection(map.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
|
|||
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.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
@ -133,8 +134,11 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
|
|||
ValidationResult result;
|
||||
if (isNotBlank(theRawResource)) {
|
||||
result = validator.validateWithResult(theRawResource);
|
||||
} else {
|
||||
} else if (theResource != null) {
|
||||
result = validator.validateWithResult(theResource);
|
||||
} else {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "cantValidateWithNoResource");
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
|
||||
if (result.isSuccessful()) {
|
||||
|
@ -160,11 +164,11 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
|
|||
boolean hasId = theCtx.getResource().getIdElement().hasIdPart();
|
||||
if (myMode == ValidationModeEnum.CREATE) {
|
||||
if (hasId) {
|
||||
throw new InvalidRequestException("Resource has an ID - ID must not be populated for a FHIR create");
|
||||
throw new UnprocessableEntityException("Resource has an ID - ID must not be populated for a FHIR create");
|
||||
}
|
||||
} else if (myMode == ValidationModeEnum.UPDATE) {
|
||||
if (hasId == false) {
|
||||
throw new InvalidRequestException("Resource has no ID - ID must be populated for a FHIR update");
|
||||
throw new UnprocessableEntityException("Resource has no ID - ID must be populated for a FHIR update");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -492,7 +492,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, shouldUpdate, updateTime);
|
||||
if (shouldUpdate) {
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, true, updateTime);
|
||||
}
|
||||
}
|
||||
|
||||
myEntityManager.flush();
|
||||
|
|
|
@ -1,36 +1,15 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
|
||||
public interface ISearchParamRegistry {
|
||||
|
||||
Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName);
|
||||
|
||||
Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName);
|
||||
|
||||
void forceRefresh();
|
||||
|
||||
Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams();
|
||||
|
||||
Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName);
|
||||
|
||||
}
|
||||
|
|
|
@ -2309,6 +2309,11 @@ public class SearchBuilder {
|
|||
public int size() {
|
||||
return myPids.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||
|
||||
public interface IResourceIndexedSearchParamCoordsDao extends JpaRepository<ResourceIndexedSearchParamCoords, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
|
||||
public interface IResourceIndexedSearchParamDateDao extends JpaRepository<ResourceIndexedSearchParamDate, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
|
||||
public interface IResourceIndexedSearchParamNumberDao extends JpaRepository<ResourceIndexedSearchParamNumber, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||
|
||||
public interface IResourceIndexedSearchParamQuantityDao extends JpaRepository<ResourceIndexedSearchParamQuantity, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
|
||||
public interface IResourceIndexedSearchParamStringDao extends JpaRepository<ResourceIndexedSearchParamString, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
|
||||
public interface IResourceIndexedSearchParamTokenDao extends JpaRepository<ResourceIndexedSearchParamToken, Long> {
|
||||
// nothing yet
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
|
@ -32,5 +34,8 @@ public interface ITermConceptParentChildLinkDao extends JpaRepository<TermConcep
|
|||
@Query("DELETE FROM TermConceptParentChildLink t WHERE t.myCodeSystem.myId = :cs_pid")
|
||||
@Modifying
|
||||
void deleteByCodeSystemVersion(@Param("cs_pid") Long thePid);
|
||||
|
||||
@Query("SELECT t FROM TermConceptParentChildLink t WHERE t.myChildPid = :child_pid")
|
||||
Collection<TermConceptParentChildLink> findAllWithChild(@Param("child_pid") Long theConceptPid);
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
|
@ -187,6 +188,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemVersionDao myCsvDao;
|
||||
|
||||
@Override
|
||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime) {
|
||||
|
@ -198,12 +202,22 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
String codeSystemUrl = cs.getUrl();
|
||||
if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
|
||||
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
|
||||
TermCodeSystemVersion persCs = new TermCodeSystemVersion();
|
||||
persCs.setResource(retVal);
|
||||
persCs.setResourceVersionId(retVal.getVersion());
|
||||
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
|
||||
|
||||
Long codeSystemResourcePid = retVal.getId();
|
||||
TermCodeSystemVersion persCs = myCsvDao.findByCodeSystemResourceAndVersion(codeSystemResourcePid, retVal.getVersion());
|
||||
if (persCs != null) {
|
||||
ourLog.info("Code system version already exists in database");
|
||||
} else {
|
||||
|
||||
persCs = new TermCodeSystemVersion();
|
||||
persCs.setResource(retVal);
|
||||
persCs.setResourceVersionId(retVal.getVersion());
|
||||
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
|
||||
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
|
||||
myTerminologySvc.storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, persCs);
|
||||
|
||||
}
|
||||
|
||||
myTerminologySvc.storeNewCodeSystemVersion(retVal.getId(), codeSystemUrl, persCs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
|
|||
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.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
@ -143,7 +144,8 @@ public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirRe
|
|||
if (resourceToValidateById != null) {
|
||||
result = validator.validateWithResult(resourceToValidateById);
|
||||
} else {
|
||||
throw new InvalidRequestException("No resource supplied for $validate operation (resource is required unless mode is \"delete\")");
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "cantValidateWithNoResource");
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
} else if (isNotBlank(theRawResource)) {
|
||||
result = validator.validateWithResult(theRawResource);
|
||||
|
@ -180,11 +182,11 @@ public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirRe
|
|||
boolean hasId = theCtx.getResource().getIdElement().hasIdPart();
|
||||
if (myMode == ValidationModeEnum.CREATE) {
|
||||
if (hasId) {
|
||||
throw new InvalidRequestException("Resource has an ID - ID must not be populated for a FHIR create");
|
||||
throw new UnprocessableEntityException("Resource has an ID - ID must not be populated for a FHIR create");
|
||||
}
|
||||
} else if (myMode == ValidationModeEnum.UPDATE) {
|
||||
if (hasId == false) {
|
||||
throw new InvalidRequestException("Resource has no ID - ID must be populated for a FHIR update");
|
||||
throw new UnprocessableEntityException("Resource has no ID - ID must be populated for a FHIR update");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,24 +32,32 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|||
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
|
||||
public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoSearchParameterDstu3.class);
|
||||
|
||||
@Autowired
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
|
||||
@Autowired
|
||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
||||
|
||||
private void markAffectedResources(SearchParameter theResource) {
|
||||
String xpath = theResource.getXpath();
|
||||
String resourceType = xpath.substring(0, xpath.indexOf('.'));
|
||||
ourLog.info("Marking all resources of type {} for reindexing due to updated search parameter with path: {}", xpath);
|
||||
int updatedCount = myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
ourLog.info("Marked {} resources for reindexing", updatedCount);
|
||||
protected void markAffectedResources(SearchParameter theResource) {
|
||||
if (theResource != null) {
|
||||
String expression = theResource.getExpression();
|
||||
String resourceType = expression.substring(0, expression.indexOf('.'));
|
||||
ourLog.info("Marking all resources of type {} for reindexing due to updated search parameter with path: {}", expression);
|
||||
int updatedCount = myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
ourLog.info("Marked {} resources for reindexing", updatedCount);
|
||||
}
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,50 +87,67 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
|
||||
@Override
|
||||
protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
|
||||
super.postPersist(theEntity, theResource);
|
||||
markAffectedResources(theResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postUpdate(ResourceTable theEntity, SearchParameter theResource) {
|
||||
super.postUpdate(theEntity, theResource);
|
||||
markAffectedResources(theResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(SearchParameter theResourceToDelete) {
|
||||
super.preDelete(theResourceToDelete);
|
||||
markAffectedResources(theResourceToDelete);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
|
||||
super.validateResourceForStorage(theResource, theEntityToSave);
|
||||
|
||||
if (theResource.getStatus() == null) {
|
||||
throw new UnprocessableEntityException("Resource.status is missing or invalid: " + theResource.getStatusElement().getValueAsString());
|
||||
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid: " + theResource.getStatusElement().getValueAsString());
|
||||
}
|
||||
|
||||
String xpath = theResource.getXpath();
|
||||
if (isBlank(xpath)) {
|
||||
throw new UnprocessableEntityException("Resource.xpath is missing");
|
||||
|
||||
String expression = theResource.getExpression();
|
||||
if (isBlank(expression)) {
|
||||
throw new UnprocessableEntityException("SearchParameter.expression is missing");
|
||||
}
|
||||
|
||||
String[] xpathSplit = BaseSearchParamExtractor.SPLIT.split(xpath);
|
||||
|
||||
if (ElementUtil.isEmpty(theResource.getBase())) {
|
||||
throw new UnprocessableEntityException("SearchParameter.base is missing");
|
||||
}
|
||||
|
||||
expression = expression.trim();
|
||||
theResource.setExpression(expression);
|
||||
|
||||
String[] expressionSplit = BaseSearchParamExtractor.SPLIT.split(expression);
|
||||
String allResourceName = null;
|
||||
for (String nextPath : xpathSplit) {
|
||||
for (String nextPath : expressionSplit) {
|
||||
nextPath = nextPath.trim();
|
||||
|
||||
int dotIdx = nextPath.indexOf('.');
|
||||
if (dotIdx == -1) {
|
||||
throw new UnprocessableEntityException("Invalid path value \"" + nextPath + "\". Must start with a resource name");
|
||||
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name");
|
||||
}
|
||||
|
||||
|
||||
String resourceName = nextPath.substring(0, dotIdx);
|
||||
try {
|
||||
getContext().getResourceDefinition(resourceName);
|
||||
} catch (DataFormatException e) {
|
||||
throw new UnprocessableEntityException("Invalid path value \"" + nextPath + "\": " + e.getMessage());
|
||||
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\": " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
if (allResourceName == null) {
|
||||
allResourceName = resourceName;
|
||||
} else {
|
||||
if (!allResourceName.equals(resourceName)) {
|
||||
throw new UnprocessableEntityException("Invalid path value \"" + nextPath + "\". All paths in a single SearchParameter must match the same resource type");
|
||||
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". All paths in a single SearchParameter must match the same resource type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -33,6 +33,7 @@ import org.hl7.fhir.dstu3.model.CodeSystem;
|
|||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||
import org.hl7.fhir.dstu3.model.UriType;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
|
@ -82,12 +83,12 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
|
||||
return retVal;
|
||||
|
||||
// ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
||||
// ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
||||
//
|
||||
// ValueSet retVal = new ValueSet();
|
||||
// retVal.getMeta().setLastUpdated(new Date());
|
||||
// retVal.setExpansion(expansion);
|
||||
// return retVal;
|
||||
// ValueSet retVal = new ValueSet();
|
||||
// retVal.getMeta().setLastUpdated(new Date());
|
||||
// retVal.setExpansion(expansion);
|
||||
// return retVal;
|
||||
}
|
||||
|
||||
private void validateIncludes(String name, List<ConceptSetComponent> listToValidate) {
|
||||
|
@ -137,11 +138,11 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
public ValueSet expand(ValueSet source, String theFilter) {
|
||||
ValueSet toExpand = new ValueSet();
|
||||
|
||||
// for (UriType next : source.getCompose().getInclude()) {
|
||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||
// include.setSystem(next.getValue());
|
||||
// addFilterIfPresent(theFilter, include);
|
||||
// }
|
||||
// for (UriType next : source.getCompose().getInclude()) {
|
||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||
// include.setSystem(next.getValue());
|
||||
// addFilterIfPresent(theFilter, include);
|
||||
// }
|
||||
|
||||
for (ConceptSetComponent next : source.getCompose().getInclude()) {
|
||||
toExpand.getCompose().addInclude(next);
|
||||
|
@ -155,18 +156,41 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
toExpand.getCompose().getExclude().addAll(source.getCompose().getExclude());
|
||||
|
||||
ValueSet retVal = doExpand(toExpand);
|
||||
|
||||
if (isNotBlank(theFilter)) {
|
||||
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
}
|
||||
|
||||
private void applyFilter(IntegerType theTotalElement, List<ValueSetExpansionContainsComponent> theContains, String theFilter) {
|
||||
|
||||
for (int idx = 0; idx < theContains.size(); idx++) {
|
||||
ValueSetExpansionContainsComponent next = theContains.get(idx);
|
||||
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
|
||||
theContains.remove(idx);
|
||||
idx--;
|
||||
if (theTotalElement.getValue() != null) {
|
||||
theTotalElement.setValue(theTotalElement.getValue() - 1);
|
||||
}
|
||||
}
|
||||
applyFilter(theTotalElement, next.getContains(), theFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
||||
if (isNotBlank(theFilter)) {
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
|
||||
if (ElementUtil.isEmpty(include.getConcept())) {
|
||||
if (isNotBlank(theFilter)) {
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
List<IIdType> valueSetIds = Collections.emptyList();
|
||||
|
@ -226,7 +250,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||
}
|
||||
|
||||
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode, Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode,
|
||||
Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
||||
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
|
|
|
@ -383,7 +383,8 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
IFhirResourceDao resourceDao = getDaoOrThrowException(res.getClass());
|
||||
res.setId((String) null);
|
||||
DaoMethodOutcome outcome;
|
||||
outcome = resourceDao.create(res, nextReqEntry.getRequest().getIfNoneExist(), false, theRequestDetails);
|
||||
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
||||
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
|
||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||
if (outcome.getCreated() == false) {
|
||||
|
@ -489,7 +490,9 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
IPrimitiveType<Date> deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource);
|
||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
boolean shouldUpdate = !nonUpdatedEntities.contains(nextOutcome.getEntity());
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, shouldUpdate, shouldUpdate, updateTime);
|
||||
if (shouldUpdate) {
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, shouldUpdate, true, updateTime);
|
||||
}
|
||||
}
|
||||
|
||||
myEntityManager.flush();
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.hl7.fhir.dstu3.model.ContactPoint;
|
|||
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||
import org.hl7.fhir.dstu3.model.Duration;
|
||||
import org.hl7.fhir.dstu3.model.Enumeration;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
import org.hl7.fhir.dstu3.model.HumanName;
|
||||
import org.hl7.fhir.dstu3.model.Identifier;
|
||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||
|
@ -520,7 +521,16 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||
// }
|
||||
|
||||
for (Object nextObject : extractValues(nextPath, theResource)) {
|
||||
|
||||
if (nextObject instanceof Extension) {
|
||||
Extension nextExtension = (Extension)nextObject;
|
||||
nextObject = nextExtension.getValue();
|
||||
}
|
||||
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Patient:language
|
||||
if (nextObject instanceof PatientCommunicationComponent) {
|
||||
PatientCommunicationComponent nextValue = (PatientCommunicationComponent) nextObject;
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -35,6 +35,7 @@ import org.apache.commons.lang3.time.DateUtils;
|
|||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.SearchParameter;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
|
@ -50,19 +51,43 @@ import ca.uhn.fhir.rest.server.IBundleProvider;
|
|||
public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamRegistryDstu3.class);
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<SearchParameter> mySpDao;
|
||||
|
||||
private long myLastRefresh;
|
||||
|
||||
private volatile Map<String, Map<String, RuntimeSearchParam>> myActiveSearchParams;
|
||||
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
|
||||
private long myLastRefresh;
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<SearchParameter> mySpDao;
|
||||
|
||||
@Override
|
||||
public void forceRefresh() {
|
||||
myLastRefresh = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
|
||||
refreshCacheIfNeccesary();
|
||||
return myActiveSearchParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||
refreshCacheIfNeccesary();
|
||||
return myActiveSearchParams.get(theResourceName);
|
||||
}
|
||||
|
||||
private Map<String, RuntimeSearchParam> getSearchParamMap(Map<String, Map<String, RuntimeSearchParam>> searchParams, String theResourceName) {
|
||||
Map<String, RuntimeSearchParam> retVal = searchParams.get(theResourceName);
|
||||
if (retVal == null) {
|
||||
retVal = new HashMap<String, RuntimeSearchParam>();
|
||||
searchParams.put(theResourceName, retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void refreshCacheIfNeccesary() {
|
||||
long refreshInterval = 60 * DateUtils.MILLIS_PER_MINUTE;
|
||||
if (System.currentTimeMillis() - refreshInterval > myLastRefresh) {
|
||||
StopWatch sw = new StopWatch();
|
||||
|
@ -91,7 +116,7 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
if (runtimeSp == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int dotIdx = runtimeSp.getPath().indexOf('.');
|
||||
if (dotIdx == -1) {
|
||||
ourLog.warn("Can not determine resource type of {}", runtimeSp.getPath());
|
||||
|
@ -113,14 +138,14 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
if (nextSp.getStatus() != RuntimeSearchParamStatusEnum.ACTIVE) {
|
||||
nextSp = null;
|
||||
}
|
||||
|
||||
|
||||
if (!activeSearchParams.containsKey(nextEntry.getKey())) {
|
||||
activeSearchParams.put(nextEntry.getKey(), new HashMap<String, RuntimeSearchParam>());
|
||||
}
|
||||
if (activeSearchParams.containsKey(nextEntry.getKey())) {
|
||||
ourLog.info("Replacing existing/built in search param {}:{} with new one", nextEntry.getKey(), nextName);
|
||||
ourLog.debug("Replacing existing/built in search param {}:{} with new one", nextEntry.getKey(), nextName);
|
||||
}
|
||||
|
||||
|
||||
if (nextSp != null) {
|
||||
activeSearchParams.get(nextEntry.getKey()).put(nextName, nextSp);
|
||||
} else {
|
||||
|
@ -134,28 +159,12 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
myLastRefresh = System.currentTimeMillis();
|
||||
ourLog.info("Refreshed search parameter cache in {}ms", sw.getMillis());
|
||||
}
|
||||
|
||||
return myActiveSearchParams.get(theResourceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceRefresh() {
|
||||
myLastRefresh = 0;
|
||||
}
|
||||
|
||||
private Map<String, RuntimeSearchParam> getSearchParamMap(Map<String, Map<String, RuntimeSearchParam>> searchParams, String theResourceName) {
|
||||
Map<String, RuntimeSearchParam> retVal = searchParams.get(theResourceName);
|
||||
if (retVal == null) {
|
||||
retVal = new HashMap<String, RuntimeSearchParam>();
|
||||
searchParams.put(theResourceName, retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private RuntimeSearchParam toRuntimeSp(SearchParameter theNextSp) {
|
||||
String name = theNextSp.getCode();
|
||||
String description = theNextSp.getDescription();
|
||||
String path = theNextSp.getXpath();
|
||||
String path = theNextSp.getExpression();
|
||||
RestSearchParameterTypeEnum paramType = null;
|
||||
RuntimeSearchParamStatusEnum status = null;
|
||||
switch (theNextSp.getType()) {
|
||||
|
@ -208,7 +217,9 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
return null;
|
||||
}
|
||||
|
||||
RuntimeSearchParam retVal = new RuntimeSearchParam(name, description, path, paramType, providesMembershipInCompartments, targets, status);
|
||||
IIdType id = theNextSp.getIdElement();
|
||||
String uri = "";
|
||||
RuntimeSearchParam retVal = new RuntimeSearchParam(id, uri, name, description, path, paramType, null, providesMembershipInCompartments, targets, status);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
return myResourcePid;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setParamName(String theName) {
|
||||
myParamName = theName;
|
||||
}
|
||||
|
|
|
@ -233,12 +233,14 @@ public class TermConcept implements Serializable {
|
|||
@PreUpdate
|
||||
@PrePersist
|
||||
public void prePersist() {
|
||||
Set<Long> parentPids = new HashSet<Long>();
|
||||
TermConcept entity = this;
|
||||
parentPids(entity, parentPids);
|
||||
entity.setParentPids(parentPids);
|
||||
|
||||
ourLog.trace("Code {}/{} has parents {}", entity.getId(), entity.getCode(), entity.getParentPidsAsString());
|
||||
if (myParentPids == null) {
|
||||
Set<Long> parentPids = new HashSet<Long>();
|
||||
TermConcept entity = this;
|
||||
parentPids(entity, parentPids);
|
||||
entity.setParentPids(parentPids);
|
||||
|
||||
ourLog.trace("Code {}/{} has parents {}", entity.getId(), entity.getCode(), entity.getParentPidsAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public void setCode(String theCode) {
|
||||
|
@ -280,6 +282,10 @@ public class TermConcept implements Serializable {
|
|||
myParentPids = b.toString();
|
||||
}
|
||||
|
||||
public void setParentPids(String theParentPids) {
|
||||
myParentPids = theParentPids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("code", myCode).append("display", myDisplay).build();
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -36,77 +36,38 @@ import javax.persistence.SequenceGenerator;
|
|||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="TRM_CONCEPT_PC_LINK")
|
||||
@Table(name = "TRM_CONCEPT_PC_LINK")
|
||||
public class TermConceptParentChildLink implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(name="CHILD_PID", nullable=false, referencedColumnName="PID", foreignKey=@ForeignKey(name="FK_TERM_CONCEPTPC_CHILD"))
|
||||
@JoinColumn(name = "CHILD_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CHILD"))
|
||||
private TermConcept myChild;
|
||||
|
||||
@Column(name = "CHILD_PID", insertable = false, updatable = false)
|
||||
private Long myChildPid;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(name="CODESYSTEM_PID", nullable=false, foreignKey=@ForeignKey(name="FK_TERM_CONCEPTPC_CS"))
|
||||
@JoinColumn(name = "CODESYSTEM_PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CS"))
|
||||
private TermCodeSystemVersion myCodeSystem;
|
||||
|
||||
@ManyToOne(cascade= {})
|
||||
@JoinColumn(name="PARENT_PID", nullable=false, referencedColumnName="PID", foreignKey=@ForeignKey(name="FK_TERM_CONCEPTPC_PARENT"))
|
||||
@ManyToOne(cascade = {})
|
||||
@JoinColumn(name = "PARENT_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_PARENT"))
|
||||
private TermConcept myParent;
|
||||
|
||||
@Column(name = "PARENT_PID", insertable = false, updatable = false)
|
||||
private Long myParentPid;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name="SEQ_CONCEPT_PC_PID", sequenceName="SEQ_CONCEPT_PC_PID")
|
||||
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CONCEPT_PC_PID")
|
||||
@Column(name="PID")
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PC_PID", sequenceName = "SEQ_CONCEPT_PC_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PC_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myPid;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name="REL_TYPE", length=5, nullable=true)
|
||||
@Column(name = "REL_TYPE", length = 5, nullable = true)
|
||||
private RelationshipTypeEnum myRelationshipType;
|
||||
|
||||
public TermConcept getChild() {
|
||||
return myChild;
|
||||
}
|
||||
|
||||
public RelationshipTypeEnum getRelationshipType() {
|
||||
return myRelationshipType;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion getCodeSystem() {
|
||||
return myCodeSystem;
|
||||
}
|
||||
|
||||
public TermConcept getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
public void setChild(TermConcept theChild) {
|
||||
myChild = theChild;
|
||||
}
|
||||
|
||||
public void setCodeSystem(TermCodeSystemVersion theCodeSystem) {
|
||||
myCodeSystem = theCodeSystem;
|
||||
}
|
||||
|
||||
public void setParent(TermConcept theParent) {
|
||||
myParent = theParent;
|
||||
}
|
||||
|
||||
|
||||
public void setRelationshipType(RelationshipTypeEnum theRelationshipType) {
|
||||
myRelationshipType = theRelationshipType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myChild == null) ? 0 : myChild.hashCode());
|
||||
result = prime * result + ((myCodeSystem == null) ? 0 : myCodeSystem.hashCode());
|
||||
result = prime * result + ((myParent == null) ? 0 : myParent.hashCode());
|
||||
result = prime * result + ((myRelationshipType == null) ? 0 : myRelationshipType.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
|
@ -136,15 +97,64 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public enum RelationshipTypeEnum{
|
||||
// ********************************************
|
||||
// IF YOU ADD HERE MAKE SURE ORDER IS PRESERVED
|
||||
ISA
|
||||
public TermConcept getChild() {
|
||||
return myChild;
|
||||
}
|
||||
|
||||
public Long getChildPid() {
|
||||
return myChildPid;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion getCodeSystem() {
|
||||
return myCodeSystem;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myPid;
|
||||
}
|
||||
|
||||
public TermConcept getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
public Long getParentPid() {
|
||||
return myParentPid;
|
||||
}
|
||||
|
||||
public RelationshipTypeEnum getRelationshipType() {
|
||||
return myRelationshipType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myChild == null) ? 0 : myChild.hashCode());
|
||||
result = prime * result + ((myCodeSystem == null) ? 0 : myCodeSystem.hashCode());
|
||||
result = prime * result + ((myParent == null) ? 0 : myParent.hashCode());
|
||||
result = prime * result + ((myRelationshipType == null) ? 0 : myRelationshipType.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setChild(TermConcept theChild) {
|
||||
myChild = theChild;
|
||||
}
|
||||
|
||||
public void setCodeSystem(TermCodeSystemVersion theCodeSystem) {
|
||||
myCodeSystem = theCodeSystem;
|
||||
}
|
||||
|
||||
public void setParent(TermConcept theParent) {
|
||||
myParent = theParent;
|
||||
}
|
||||
|
||||
public void setRelationshipType(RelationshipTypeEnum theRelationshipType) {
|
||||
myRelationshipType = theRelationshipType;
|
||||
}
|
||||
|
||||
public enum RelationshipTypeEnum {
|
||||
// ********************************************
|
||||
// IF YOU ADD HERE MAKE SURE ORDER IS PRESERVED
|
||||
ISA
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.search;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -30,10 +31,12 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.jpa.dao.IDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||
import ca.uhn.fhir.rest.server.BasePagingProvider;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
|
||||
public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider {
|
||||
public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider {
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager thePlatformTransactionManager;
|
||||
|
@ -46,29 +49,36 @@ public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider {
|
|||
@Autowired
|
||||
private IFhirSystemDao<?, ?> theDao;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @deprecated Use {@link DatabaseBackedPagingProvider} as this constructor has no purpose
|
||||
*/
|
||||
@Deprecated
|
||||
public DatabaseBackedPagingProvider(int theSize) {
|
||||
super(theSize);
|
||||
this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public DatabaseBackedPagingProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized IBundleProvider retrieveResultList(String theId) {
|
||||
IBundleProvider retVal = super.retrieveResultList(theId);
|
||||
if (retVal == null) {
|
||||
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao);
|
||||
if (!provider.ensureSearchEntityLoaded()) {
|
||||
return null;
|
||||
}
|
||||
retVal = provider;
|
||||
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao);
|
||||
if (!provider.ensureSearchEntityLoaded()) {
|
||||
return null;
|
||||
}
|
||||
return retVal;
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String storeResultList(IBundleProvider theList) {
|
||||
if (theList instanceof PersistedJpaBundleProvider) {
|
||||
return ((PersistedJpaBundleProvider)theList).getSearchUuid();
|
||||
}
|
||||
return super.storeResultList(theList);
|
||||
String uuid = theList.getUuid();
|
||||
Validate.notNull(uuid);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,7 @@ package ca.uhn.fhir.jpa.search;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
|
@ -49,11 +43,7 @@ import ca.uhn.fhir.jpa.dao.IDao;
|
|||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
||||
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
||||
|
@ -220,7 +210,7 @@ public final class PersistedJpaBundleProvider implements IBundleProvider {
|
|||
});
|
||||
}
|
||||
|
||||
public String getSearchUuid() {
|
||||
public String getUuid() {
|
||||
return myUuid;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,11 @@ package ca.uhn.fhir.jpa.term;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -33,6 +35,7 @@ import javax.persistence.EntityManager;
|
|||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
@ -45,7 +48,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
|
@ -66,6 +72,7 @@ import ca.uhn.fhir.util.ObjectUtil;
|
|||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
|
||||
public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
private static boolean ourForceSaveDeferredAlwaysForUnitTest;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiTerminologySvc.class);
|
||||
private static final Object PLACEHOLDER_OBJECT = new Object();
|
||||
|
||||
|
@ -94,8 +101,11 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
|
||||
private boolean myProcessDeferred = true;
|
||||
private long myNextReindexPass;
|
||||
private boolean myProcessDeferred = true;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTransactionMgr;
|
||||
|
||||
private boolean addToSet(Set<TermConcept> theSetToPopulate, TermConcept theConcept) {
|
||||
boolean retVal = theSetToPopulate.add(theConcept);
|
||||
|
@ -108,6 +118,25 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private int ensureParentsSaved(Collection<TermConceptParentChildLink> theParents) {
|
||||
ourLog.trace("Checking {} parents", theParents.size());
|
||||
int retVal = 0;
|
||||
|
||||
for (TermConceptParentChildLink nextLink : theParents) {
|
||||
if (nextLink.getRelationshipType() == RelationshipTypeEnum.ISA) {
|
||||
TermConcept nextParent = nextLink.getParent();
|
||||
retVal += ensureParentsSaved(nextParent.getParents());
|
||||
if (nextParent.getId() == null) {
|
||||
myConceptDao.saveAndFlush(nextParent);
|
||||
retVal++;
|
||||
ourLog.debug("Saved parent code {} and got id {}", nextParent.getCode(), nextParent.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void fetchChildren(TermConcept theConcept, Set<TermConcept> theSetToPopulate) {
|
||||
for (TermConceptParentChildLink nextChildLink : theConcept.getChildren()) {
|
||||
TermConcept nextChild = nextChildLink.getChild();
|
||||
|
@ -175,6 +204,15 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
* @param theSystem The code system
|
||||
* @param theCode The code
|
||||
*/
|
||||
protected List<VersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Set<TermConcept> findCodesBelow(Long theCodeSystemResourcePid, Long theCodeSystemVersionPid, String theCode) {
|
||||
|
@ -206,7 +244,6 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ArrayList<VersionIndependentConcept> retVal = toVersionIndependentConcepts(theSystem, codes);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
* @param theSystem The code system
|
||||
|
@ -215,16 +252,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
protected List<VersionIndependentConcept> findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
* @param theSystem The code system
|
||||
* @param theCode The code
|
||||
*/
|
||||
protected List<VersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private TermCodeSystemVersion findCurrentCodeSystemVersionForSystem(String theCodeSystem) {
|
||||
TermCodeSystem cs = getCodeSystem(theCodeSystem);
|
||||
if (cs == null || cs.getCurrentVersion() == null) {
|
||||
|
@ -233,11 +261,12 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
TermCodeSystemVersion csv = cs.getCurrentVersion();
|
||||
return csv;
|
||||
}
|
||||
|
||||
private TermCodeSystem getCodeSystem(String theSystem) {
|
||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(theSystem);
|
||||
return cs;
|
||||
}
|
||||
|
||||
|
||||
private void persistChildren(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, IdentityHashMap<TermConcept, Object> theConceptsStack, int theTotalConcepts) {
|
||||
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
||||
return;
|
||||
|
@ -271,15 +300,99 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
|
||||
}
|
||||
|
||||
private void saveConceptLink(TermConceptParentChildLink next) {
|
||||
if (next.getId() == null) {
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
if (theNext.getCodeSystem() != null) {
|
||||
return;
|
||||
}
|
||||
theNext.setCodeSystem(theCodeSystemVersion);
|
||||
for (TermConceptParentChildLink next : theNext.getChildren()) {
|
||||
populateVersion(next.getChild(), theCodeSystemVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayListMultimap<Long, Long> myChildToParentPidCache;
|
||||
|
||||
private void processReindexing() {
|
||||
if (System.currentTimeMillis() < myNextReindexPass && !ourForceSaveDeferredAlwaysForUnitTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(myTransactionMgr);
|
||||
tt.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
|
||||
int maxResult = 1000;
|
||||
Page<TermConcept> concepts = myConceptDao.findResourcesRequiringReindexing(new PageRequest(0, maxResult));
|
||||
if (concepts.hasContent() == false) {
|
||||
myNextReindexPass = System.currentTimeMillis() + DateUtils.MILLIS_PER_MINUTE;
|
||||
myChildToParentPidCache = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (myChildToParentPidCache == null) {
|
||||
myChildToParentPidCache = ArrayListMultimap.create();
|
||||
}
|
||||
|
||||
ourLog.info("Indexing {} / {} concepts", concepts.getContent().size(), concepts.getTotalElements());
|
||||
|
||||
int count = 0;
|
||||
StopWatch stopwatch = new StopWatch();
|
||||
|
||||
for (TermConcept nextConcept : concepts) {
|
||||
|
||||
StringBuilder parentsBuilder = new StringBuilder();
|
||||
createParentsString(parentsBuilder, nextConcept.getId());
|
||||
nextConcept.setParentPids(parentsBuilder.toString());
|
||||
|
||||
saveConcept(nextConcept);
|
||||
count++;
|
||||
}
|
||||
|
||||
ourLog.info("Indexed {} / {} concepts in {}ms - Avg {}ms / resource", new Object[] { count, concepts.getContent().size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(count) });
|
||||
}
|
||||
|
||||
private void createParentsString(StringBuilder theParentsBuilder, Long theConceptPid) {
|
||||
Validate.notNull(theConceptPid, "theConceptPid must not be null");
|
||||
List<Long> parents = myChildToParentPidCache.get(theConceptPid);
|
||||
if (parents.contains(-1L)) {
|
||||
return;
|
||||
} else if (parents.isEmpty()) {
|
||||
Collection<TermConceptParentChildLink> parentLinks = myConceptParentChildLinkDao.findAllWithChild(theConceptPid);
|
||||
if (parentLinks.isEmpty()) {
|
||||
myChildToParentPidCache.put(theConceptPid, -1L);
|
||||
return;
|
||||
} else {
|
||||
for (TermConceptParentChildLink next : parentLinks) {
|
||||
myChildToParentPidCache.put(theConceptPid, next.getParentPid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Long nextParent : parents) {
|
||||
if (theParentsBuilder.length() > 0) {
|
||||
theParentsBuilder.append(' ');
|
||||
}
|
||||
theParentsBuilder.append(nextParent);
|
||||
createParentsString(theParentsBuilder, nextParent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private int saveConcept(TermConcept theConcept) {
|
||||
int retVal = 0;
|
||||
retVal += ensureParentsSaved(theConcept.getParents());
|
||||
|
||||
/*
|
||||
* If the concept has an ID, we're reindexing, so there's no need to
|
||||
* save parent concepts first (it's way too slow to do that)
|
||||
*/
|
||||
if (theConcept.getId() == null) {
|
||||
retVal += ensureParentsSaved(theConcept.getParents());
|
||||
}
|
||||
|
||||
if (theConcept.getId() == null || theConcept.getIndexStatus() == null) {
|
||||
retVal++;
|
||||
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||
|
@ -289,33 +402,10 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ourLog.trace("Saved {} and got PID {}", theConcept.getCode(), theConcept.getId());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private int ensureParentsSaved(Collection<TermConceptParentChildLink> theParents) {
|
||||
ourLog.trace("Checking {} parents", theParents.size());
|
||||
int retVal = 0;
|
||||
|
||||
for (TermConceptParentChildLink nextLink : theParents) {
|
||||
if (nextLink.getRelationshipType() == RelationshipTypeEnum.ISA) {
|
||||
TermConcept nextParent = nextLink.getParent();
|
||||
retVal += ensureParentsSaved(nextParent.getParents());
|
||||
if (nextParent.getId() == null) {
|
||||
myConceptDao.saveAndFlush(nextParent);
|
||||
retVal++;
|
||||
ourLog.debug("Saved parent code {} and got id {}", nextParent.getCode(), nextParent.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
if (theNext.getCodeSystem() != null) {
|
||||
return;
|
||||
}
|
||||
theNext.setCodeSystem(theCodeSystemVersion);
|
||||
for (TermConceptParentChildLink next : theNext.getChildren()) {
|
||||
populateVersion(next.getChild(), theCodeSystemVersion);
|
||||
|
||||
private void saveConceptLink(TermConceptParentChildLink next) {
|
||||
if (next.getId() == null) {
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,43 +458,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ourLog.info("All deferred concepts and relationships have now been synchronized to the database");
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTransactionMgr;
|
||||
|
||||
private void processReindexing() {
|
||||
if (System.currentTimeMillis() < myNextReindexPass) {
|
||||
return;
|
||||
}
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(myTransactionMgr);
|
||||
tt.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
|
||||
int maxResult = 1000;
|
||||
Page<TermConcept> resources = myConceptDao.findResourcesRequiringReindexing(new PageRequest(0, maxResult));
|
||||
if (resources.hasContent() == false) {
|
||||
myNextReindexPass = System.currentTimeMillis() + DateUtils.MILLIS_PER_MINUTE;
|
||||
return;
|
||||
}
|
||||
|
||||
ourLog.info("Indexing {} / {} concepts", resources.getContent().size(), resources.getTotalElements());
|
||||
|
||||
int count = 0;
|
||||
StopWatch stopwatch = new StopWatch();
|
||||
|
||||
for (TermConcept resourceTable : resources) {
|
||||
saveConcept(resourceTable);
|
||||
count++;
|
||||
}
|
||||
|
||||
ourLog.info("Indexed {} / {} concepts in {}ms - Avg {}ms / resource", new Object[] { count, resources.getContent().size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(count) });
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessDeferred(boolean theProcessDeferred) {
|
||||
myProcessDeferred = theProcessDeferred;
|
||||
|
@ -470,7 +524,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
totalCodeCount += validateConceptForStorage(next, theCodeSystemVersion, conceptsStack, allConcepts);
|
||||
}
|
||||
|
||||
ourLog.info("Saving version");
|
||||
ourLog.info("Saving version containing {} concepts", totalCodeCount);
|
||||
|
||||
TermCodeSystemVersion codeSystemVersion = myCodeSystemVersionDao.saveAndFlush(theCodeSystemVersion);
|
||||
|
||||
|
@ -503,13 +557,13 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ourLog.info("Note that some concept saving was deferred - still have {} concepts and {} relationships", myConceptsToSaveLater.size(), myConceptLinksToSaveLater.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsSystem(String theSystem) {
|
||||
TermCodeSystem cs = getCodeSystem(theSystem);
|
||||
return cs != null;
|
||||
}
|
||||
|
||||
|
||||
private ArrayList<VersionIndependentConcept> toVersionIndependentConcepts(String theSystem, Set<TermConcept> codes) {
|
||||
ArrayList<VersionIndependentConcept> retVal = new ArrayList<VersionIndependentConcept>(codes.size());
|
||||
for (TermConcept next : codes) {
|
||||
|
@ -547,4 +601,12 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is present only for unit tests, do not call from client code
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static void setForceSaveDeferredAlwaysForUnitTest(boolean theForceSaveDeferredAlwaysForUnitTest) {
|
||||
ourForceSaveDeferredAlwaysForUnitTest = theForceSaveDeferredAlwaysForUnitTest;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
|
@ -12,7 +13,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -64,6 +65,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -79,7 +81,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
|
||||
private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set<String> addedCodes, TermConcept nextConcept) {
|
||||
if (addedCodes.add(nextConcept.getCode())) {
|
||||
ValueSetExpansionContainsComponent contains = retVal.addContains();
|
||||
|
@ -126,12 +128,12 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
for (ConceptDefinitionComponent nextChild : theNext.getConcept()) {
|
||||
foundCodeInChild |= addTreeIfItContainsCode(theSystemString, nextChild, theCode, theListToPopulate);
|
||||
}
|
||||
|
||||
|
||||
if (theCode.equals(theNext.getCode()) || foundCodeInChild) {
|
||||
theListToPopulate.add(new VersionIndependentConcept(theSystemString, theNext.getCode()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -159,17 +161,15 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
}
|
||||
|
||||
private void addDisplayFilterInexact(QueryBuilder qb, BooleanJunction<?> bool, ConceptSetFilterComponent nextFilter) {
|
||||
//@formatter:off
|
||||
Query textQuery = qb
|
||||
.phrase()
|
||||
.withSlop(2)
|
||||
.onField("myDisplay").boostedTo(4.0f)
|
||||
.andField("myDisplayEdgeNGram").boostedTo(2.0f)
|
||||
//.andField("myDisplayNGram").boostedTo(1.0f)
|
||||
//.andField("myDisplayPhonetic").boostedTo(0.5f)
|
||||
// .andField("myDisplayNGram").boostedTo(1.0f)
|
||||
// .andField("myDisplayPhonetic").boostedTo(0.5f)
|
||||
.sentence(nextFilter.getValue().toLowerCase()).createQuery();
|
||||
bool.must(textQuery);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -216,26 +216,33 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery());
|
||||
|
||||
for (ConceptSetFilterComponent nextFilter : theInclude.getFilter()) {
|
||||
if (isNotBlank(nextFilter.getValue())) {
|
||||
if (nextFilter.getProperty().equals("display:exact") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else if (nextFilter.getProperty().equals("display") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
if (nextFilter.getValue().trim().contains(" ")) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else {
|
||||
addDisplayFilterInexact(qb, bool, nextFilter);
|
||||
}
|
||||
} else if ((nextFilter.getProperty().equals("concept") || nextFilter.getProperty().equals("code")) && nextFilter.getOp() == FilterOperator.ISA) {
|
||||
TermConcept code = super.findCode(system, nextFilter.getValue());
|
||||
if (code == null) {
|
||||
throw new InvalidRequestException("Invalid filter criteria - code does not exist: {" + system + "}" + nextFilter.getValue());
|
||||
}
|
||||
if (isBlank(nextFilter.getValue()) && nextFilter.getOp() == null && isBlank(nextFilter.getProperty())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ourLog.info(" * Filtering on codes with a parent of {}/{}/{}", code.getId(), code.getCode(), code.getDisplay());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
||||
if (isBlank(nextFilter.getValue()) || nextFilter.getOp() == null || isBlank(nextFilter.getProperty())) {
|
||||
throw new InvalidRequestException("Invalid filter, must have fields populated: property op value");
|
||||
}
|
||||
|
||||
|
||||
if (nextFilter.getProperty().equals("display:exact") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else if ("display".equals(nextFilter.getProperty()) && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
if (nextFilter.getValue().trim().contains(" ")) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else {
|
||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||
addDisplayFilterInexact(qb, bool, nextFilter);
|
||||
}
|
||||
} else if ((nextFilter.getProperty().equals("concept") || nextFilter.getProperty().equals("code")) && nextFilter.getOp() == FilterOperator.ISA) {
|
||||
TermConcept code = super.findCode(system, nextFilter.getValue());
|
||||
if (code == null) {
|
||||
throw new InvalidRequestException("Invalid filter criteria - code does not exist: {" + system + "}" + nextFilter.getValue());
|
||||
}
|
||||
|
||||
ourLog.info(" * Filtering on codes with a parent of {}/{}/{}", code.getId(), code.getCode(), code.getDisplay());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
||||
} else {
|
||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,12 +250,17 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
||||
jpaQuery.setMaxResults(1000);
|
||||
|
||||
StopWatch sw = new StopWatch();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TermConcept> result = jpaQuery.getResultList();
|
||||
|
||||
ourLog.info("Expansion completed in {}ms", sw.getMillis());
|
||||
|
||||
for (TermConcept nextConcept : result) {
|
||||
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
||||
}
|
||||
|
||||
|
||||
retVal.setTotal(jpaQuery.getResultSize());
|
||||
}
|
||||
|
||||
|
@ -259,7 +271,6 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ 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.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
|
||||
|
@ -161,7 +162,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must not be populated"));
|
||||
}
|
||||
|
||||
|
@ -184,7 +185,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must be populated"));
|
||||
}
|
||||
|
||||
|
@ -207,7 +208,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must be populated"));
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,12 @@ import static org.mockito.Mockito.verify;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
@ -73,6 +75,43 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||
|
||||
/**
|
||||
* Per a message on the mailing list
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithPostDoesntUpdate() throws Exception {
|
||||
|
||||
// First bundle (name is Joshua)
|
||||
|
||||
String input = IOUtils.toString(getClass().getResource("/dstu3-post1.xml"), StandardCharsets.UTF_8);
|
||||
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||
Bundle response = mySystemDao.transaction(mySrd, request);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
assertEquals(1, response.getEntry().size());
|
||||
assertEquals("201 Created", response.getEntry().get(0).getResponse().getStatus());
|
||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||
String id = response.getEntry().get(0).getResponse().getLocation();
|
||||
|
||||
// Now the second (name is Adam, shouldn't get used)
|
||||
|
||||
input = IOUtils.toString(getClass().getResource("/dstu3-post2.xml"), StandardCharsets.UTF_8);
|
||||
request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||
response = mySystemDao.transaction(mySrd, request);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
assertEquals(1, response.getEntry().size());
|
||||
assertEquals("200 OK", response.getEntry().get(0).getResponse().getStatus());
|
||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||
String id2 = response.getEntry().get(0).getResponse().getLocation();
|
||||
assertEquals(id, id2);
|
||||
|
||||
Patient patient = myPatientDao.read(new IdType(id), mySrd);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
|
||||
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testReindexing() {
|
||||
Patient p = new Patient();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvc;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3CodeSystemTest extends BaseJpaDstu3Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3CodeSystemTest.class);
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(false);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIndexContained() throws Exception {
|
||||
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true);
|
||||
|
||||
String input = IOUtils.toString(getClass().getResource("/dstu3_codesystem_complete.json"), StandardCharsets.UTF_8);
|
||||
CodeSystem cs = myFhirCtx.newJsonParser().parseResource(CodeSystem.class, input);
|
||||
myCodeSystemDao.create(cs, mySrd);
|
||||
|
||||
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
|
||||
int outcome = mySystemDao.performReindexingPass(100);
|
||||
assertNotEquals(-1, outcome); // -1 means there was a failure
|
||||
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
|
@ -11,9 +8,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3ContainedTest extends BaseJpaDstu3Test {
|
||||
|
|
|
@ -8,9 +8,11 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.SearchParameter;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
@ -27,40 +29,60 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
@Test
|
||||
public void testCreateInvalidParamInvalidResourceName() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("PatientFoo.gender");
|
||||
fooSp.setExpression("PatientFoo.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
try {
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Invalid path value \"PatientFoo.gender\": Unknown resource name \"PatientFoo\" (this name is not known in FHIR version \"DSTU3\")", e.getMessage());
|
||||
assertEquals("Invalid SearchParameter.expression value \"PatientFoo.gender\": Unknown resource name \"PatientFoo\" (this name is not known in FHIR version \"DSTU3\")", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInvalidNoBase() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
try {
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("SearchParameter.base is missing", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInvalidParamMismatchedResourceName() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender or Observation.code");
|
||||
fooSp.setExpression("Patient.gender or Observation.code");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
try {
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Invalid path value \"Observation.code\". All paths in a single SearchParameter must match the same resource type", e.getMessage());
|
||||
assertEquals("Invalid SearchParameter.expression value \"Observation.code\". All paths in a single SearchParameter must match the same resource type", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInvalidParamNoPath() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
|
@ -70,24 +92,25 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Resource.xpath is missing", e.getMessage());
|
||||
assertEquals("SearchParameter.expression is missing", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInvalidParamNoResourceName() {
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("gender");
|
||||
fooSp.setExpression("gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
try {
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Invalid path value \"gender\". Must start with a resource name", e.getMessage());
|
||||
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,32 +118,88 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
public void testCreateInvalidParamParamNullStatus() {
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(null);
|
||||
try {
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Resource.status is missing or invalid: null", e.getMessage());
|
||||
assertEquals("SearchParameter.status is missing or invalid: null", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionWithNoValueIndexesWithoutFailure() {
|
||||
SearchParameter eyeColourSp = new SearchParameter();
|
||||
eyeColourSp.addBase("Patient");
|
||||
eyeColourSp.setCode("eyecolour");
|
||||
eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
eyeColourSp.setTitle("Eye Colour");
|
||||
eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')");
|
||||
eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(eyeColourSp, mySrd);
|
||||
|
||||
mySearchParamRegsitry.forceRefresh();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setActive(true);
|
||||
p1.addExtension().setUrl("http://acme.org/eyecolour").addExtension().setUrl("http://foo").setValue(new StringType("VAL"));
|
||||
IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchForExtension() {
|
||||
SearchParameter eyeColourSp = new SearchParameter();
|
||||
eyeColourSp.addBase("Patient");
|
||||
eyeColourSp.setCode("eyecolour");
|
||||
eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
eyeColourSp.setTitle("Eye Colour");
|
||||
eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')");
|
||||
eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(eyeColourSp, mySrd);
|
||||
|
||||
mySearchParamRegsitry.forceRefresh();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setActive(true);
|
||||
p1.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("blue"));
|
||||
IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.setActive(true);
|
||||
p2.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("green"));
|
||||
IIdType p2id = myPatientDao.create(p2).getId().toUnqualifiedVersionless();
|
||||
|
||||
// Try with custom gender SP
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add("eyecolour", new TokenParam(null, "blue"));
|
||||
IBundleProvider results = myPatientDao.search(map);
|
||||
List<String> foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||
assertThat(foundResources, contains(p1id.getValue()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithCustomParam() {
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
mySearchParamRegsitry.forceRefresh();
|
||||
|
||||
|
@ -150,16 +229,28 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||
assertThat(foundResources, contains(patId.getValue()));
|
||||
|
||||
// Delete the param
|
||||
mySearchParameterDao.delete(spId, mySrd);
|
||||
|
||||
mySearchParamRegsitry.forceRefresh();
|
||||
mySystemDao.performReindexingPass(100);
|
||||
|
||||
// Try with custom gender SP
|
||||
map = new SearchParameterMap();
|
||||
map.add("foo", new TokenParam(null, "male"));
|
||||
IBundleProvider res = myPatientDao.search(map);
|
||||
assertEquals(0, res.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithCustomParamDraft() {
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.DRAFT);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
|||
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetComposeComponent;
|
||||
|
@ -26,7 +27,9 @@ import org.junit.AfterClass;
|
|||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
|
@ -34,6 +37,8 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvc;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||
|
@ -49,9 +54,14 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
||||
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
||||
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
||||
|
||||
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(false);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -110,6 +120,37 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
createLocalVs(codeSystem);
|
||||
}
|
||||
|
||||
private CodeSystem createExternalCsDogs() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
||||
|
||||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||
cs.setResource(table);
|
||||
cs.setResourceVersionId(table.getVersion());
|
||||
|
||||
TermConcept hello = new TermConcept(cs, "hello").setDisplay("Hello");
|
||||
cs.getConcepts().add(hello);
|
||||
|
||||
TermConcept goodbye = new TermConcept(cs, "goodbye").setDisplay("Goodbye");
|
||||
cs.getConcepts().add(goodbye);
|
||||
|
||||
TermConcept dogs = new TermConcept(cs, "dogs").setDisplay("Dogs");
|
||||
cs.getConcepts().add(dogs);
|
||||
|
||||
TermConcept labrador = new TermConcept(cs, "labrador").setDisplay("Labrador");
|
||||
dogs.addChild(labrador, RelationshipTypeEnum.ISA);
|
||||
|
||||
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
||||
dogs.addChild(beagle, RelationshipTypeEnum.ISA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
private void createLocalCsAndVs() {
|
||||
//@formatter:off
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
|
@ -138,6 +179,22 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
myValueSetDao.create(valueSet, mySrd);
|
||||
}
|
||||
|
||||
private void logAndValidateValueSet(ValueSet theResult) {
|
||||
IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = parser.encodeResourceToString(theResult);
|
||||
ourLog.info(encoded);
|
||||
|
||||
FhirValidator validator = myFhirCtx.newValidator();
|
||||
validator.setValidateAgainstStandardSchema(true);
|
||||
validator.setValidateAgainstStandardSchematron(true);
|
||||
ValidationResult result = validator.validateWithResult(theResult);
|
||||
|
||||
if (!result.isSuccessful()) {
|
||||
ourLog.info(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||
fail(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeSystemCreateDuplicateFails() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
|
@ -156,28 +213,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupSnomed() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://snomed.info/sct");
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
||||
|
||||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||
cs.setResource(table);
|
||||
cs.setResourceVersionId(table.getVersion());
|
||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||
cs.getConcepts().add(parentA);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs);
|
||||
|
||||
StringType code = new StringType("ParentA");
|
||||
StringType system = new StringType("http://snomed.info/sct");
|
||||
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
assertEquals(true, outcome.isFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeSystemWithDefinedCodes() {
|
||||
//@formatter:off
|
||||
|
@ -202,160 +237,128 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithExcludeInExternalValueSet() {
|
||||
public void testExpandInvalid() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||
exclude.setSystem(URL_MY_CODE_SYSTEM);
|
||||
exclude.addConcept().setCode("childAA");
|
||||
exclude.addConcept().setCode("childAAA");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
||||
}
|
||||
|
||||
private void logAndValidateValueSet(ValueSet theResult) {
|
||||
IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = parser.encodeResourceToString(theResult);
|
||||
ourLog.info(encoded);
|
||||
|
||||
FhirValidator validator = myFhirCtx.newValidator();
|
||||
validator.setValidateAgainstStandardSchema(true);
|
||||
validator.setValidateAgainstStandardSchematron(true);
|
||||
ValidationResult result = validator.validateWithResult(theResult);
|
||||
|
||||
if (!result.isSuccessful()) {
|
||||
ourLog.info(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||
fail(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithInvalidExclude() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
/*
|
||||
* No system set on exclude
|
||||
*/
|
||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||
exclude.addConcept().setCode("childAA");
|
||||
exclude.addConcept().setCode("childAAA");
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithNoResultsInLocalValueSet1() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ZZZZ");
|
||||
include.addFilter();
|
||||
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA");
|
||||
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReindex() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ZZZZ");
|
||||
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
// Again
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithNoResultsInLocalValueSet2() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM + "AA");
|
||||
include.addConcept().setCode("A");
|
||||
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage());
|
||||
assertEquals("Invalid filter, must have fields populated: property op value", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndCodesInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
public void testExpandWithCodesAndDisplayFilterBlank() {
|
||||
CodeSystem codeSystem = createExternalCsDogs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ParentA");
|
||||
include.addConcept().setCode("childAA");
|
||||
include.addConcept().setCode("childAAA");
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addFilter()
|
||||
.setProperty("concept")
|
||||
.setOp(FilterOperator.ISA)
|
||||
.setValue("dogs");
|
||||
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
ValueSet result = myValueSetDao.expand(valueSet, "");
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
assertEquals(4, result.getExpansion().getTotal());
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA"));
|
||||
assertThat(codes, containsInAnyOrder("hello", "goodbye", "labrador", "beagle"));
|
||||
|
||||
int idx = codes.indexOf("childAA");
|
||||
assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode());
|
||||
assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay());
|
||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndFilterInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
public void testExpandWithCodesAndDisplayFilterPartialOnFilter() {
|
||||
CodeSystem codeSystem = createExternalCsDogs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addFilter()
|
||||
.setProperty("concept")
|
||||
.setOp(FilterOperator.ISA)
|
||||
.setValue("dogs");
|
||||
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
assertEquals(1, result.getExpansion().getTotal());
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentB"));
|
||||
assertThat(codes, containsInAnyOrder("labrador"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithCodesAndDisplayFilterPartialOnCodes() {
|
||||
CodeSystem codeSystem = createExternalCsDogs();
|
||||
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl())
|
||||
.addFilter()
|
||||
.setProperty("concept")
|
||||
.setOp(FilterOperator.ISA)
|
||||
.setValue("dogs");
|
||||
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(valueSet, "hel");
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
assertEquals(1, result.getExpansion().getTotal());
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("hello"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithCodesAndDisplayFilterPartialOnExpansion() {
|
||||
CodeSystem codeSystem = createExternalCsDogs();
|
||||
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl());
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
assertEquals(1, result.getExpansion().getTotal());
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("labrador"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -392,6 +395,127 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithExcludeInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||
exclude.setSystem(URL_MY_CODE_SYSTEM);
|
||||
exclude.addConcept().setCode("childAA");
|
||||
exclude.addConcept().setCode("childAAA");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithInvalidExclude() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
/*
|
||||
* No system set on exclude
|
||||
*/
|
||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||
exclude.addConcept().setCode("childAA");
|
||||
exclude.addConcept().setCode("childAAA");
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithIsAInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithIsAInExternalValueSetReindex() {
|
||||
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true);
|
||||
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
|
||||
mySystemDao.performReindexingPass(100);
|
||||
mySystemDao.performReindexingPass(100);
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithNoResultsInLocalValueSet1() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ZZZZ");
|
||||
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithNoResultsInLocalValueSet2() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM + "AA");
|
||||
include.addConcept().setCode("A");
|
||||
|
||||
try {
|
||||
myValueSetDao.expand(vs, null);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
||||
createLocalCsAndVs();
|
||||
|
@ -422,6 +546,29 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
//
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndCodesInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ParentA");
|
||||
include.addConcept().setCode("childAA");
|
||||
include.addConcept().setCode("childAAA");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA"));
|
||||
|
||||
int idx = codes.indexOf("childAA");
|
||||
assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode());
|
||||
assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay());
|
||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndCodesInLocalValueSet() {
|
||||
createLocalCsAndVs();
|
||||
|
@ -449,6 +596,43 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
//
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndDisplayFilterBlank() {
|
||||
CodeSystem codeSystem = createExternalCsDogs();
|
||||
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
valueSet.getCompose()
|
||||
.addInclude()
|
||||
.setSystem(codeSystem.getUrl());
|
||||
|
||||
ValueSet result = myValueSetDao.expand(valueSet, "");
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
assertEquals(5, result.getExpansion().getTotal());
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("hello", "goodbye", "dogs", "labrador", "beagle"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithSystemAndFilterInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
logAndValidateValueSet(result);
|
||||
|
||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||
assertThat(codes, containsInAnyOrder("ParentB"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexingIsDeferredForLargeCodeSystems() {
|
||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
||||
|
@ -489,6 +673,28 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
assertThat(encoded, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupSnomed() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://snomed.info/sct");
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
||||
|
||||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||
cs.setResource(table);
|
||||
cs.setResourceVersionId(table.getVersion());
|
||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||
cs.getConcepts().add(parentA);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs);
|
||||
|
||||
StringType code = new StringType("ParentA");
|
||||
StringType system = new StringType("http://snomed.info/sct");
|
||||
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
assertEquals(true, outcome.isFound());
|
||||
}
|
||||
|
||||
/**
|
||||
* Can't currently abort costly
|
||||
*/
|
||||
|
@ -523,6 +729,30 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReindex() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
include.addConcept().setCode("ZZZZ");
|
||||
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
// Again
|
||||
mySystemDao.markAllResourcesForReindexing();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
mySystemDao.performReindexingPass(null);
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeAboveLocalCodesystem() {
|
||||
createLocalCsAndVs();
|
||||
|
@ -565,107 +795,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeBelowLocalCodesystem() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
Observation obsAA = new Observation();
|
||||
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
||||
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsBA = new Observation();
|
||||
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
||||
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsCA = new Observation();
|
||||
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
||||
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInBuiltInValueSet() {
|
||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
SearchParameterMap params;
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||
|
||||
// No codes in this one
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||
|
||||
// Invalid VS
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN));
|
||||
try {
|
||||
myAllergyIntoleranceDao.search(params);
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Todo: not yet implemented
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSearchCodeNotInBuiltInValueSet() {
|
||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
SearchParameterMap params;
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||
|
||||
// No codes in this one
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||
|
||||
// Invalid VS
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN));
|
||||
try {
|
||||
myAllergyIntoleranceDao.search(params);
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeBelowBuiltInCodesystem() {
|
||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||
|
@ -753,6 +882,68 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchCodeBelowLocalCodesystem() {
|
||||
createLocalCsAndVs();
|
||||
|
||||
Observation obsAA = new Observation();
|
||||
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
||||
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsBA = new Observation();
|
||||
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
||||
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation obsCA = new Observation();
|
||||
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
||||
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInBuiltInValueSet() {
|
||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
SearchParameterMap params;
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||
|
||||
// No codes in this one
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||
|
||||
// Invalid VS
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN));
|
||||
try {
|
||||
myAllergyIntoleranceDao.search(params);
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInEmptyValueSet() {
|
||||
ValueSet valueSet = new ValueSet();
|
||||
|
@ -777,40 +968,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
ourLog.info("testSearchCodeInEmptyValueSet done");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS");
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap params;
|
||||
|
||||
ourLog.info("testSearchCodeInEmptyValueSet without status");
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||
try {
|
||||
myObservationDao.search(params);
|
||||
} catch(InvalidRequestException e) {
|
||||
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
||||
}
|
||||
|
||||
// Now let's update
|
||||
valueSet = new ValueSet();
|
||||
valueSet.setId(vsid);
|
||||
valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A");
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||
params.add(Observation.SP_STATUS, new TokenParam(null, "final"));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInExternalCodesystem() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
@ -870,6 +1027,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInLocalCodesystem() {
|
||||
createLocalCsAndVs();
|
||||
|
@ -892,6 +1050,78 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS");
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap params;
|
||||
|
||||
ourLog.info("testSearchCodeInEmptyValueSet without status");
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||
try {
|
||||
myObservationDao.search(params);
|
||||
} catch(InvalidRequestException e) {
|
||||
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
||||
}
|
||||
|
||||
// Now let's update
|
||||
valueSet = new ValueSet();
|
||||
valueSet.setId(vsid);
|
||||
valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A");
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||
params.add(Observation.SP_STATUS, new TokenParam(null, "final"));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo: not yet implemented
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSearchCodeNotInBuiltInValueSet() {
|
||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
SearchParameterMap params;
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||
|
||||
// No codes in this one
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN));
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||
|
||||
// Invalid VS
|
||||
params = new SearchParameterMap();
|
||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN));
|
||||
try {
|
||||
myAllergyIntoleranceDao.search(params);
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ArrayList<String> toCodesContains(List<ValueSetExpansionContainsComponent> theContains) {
|
||||
ArrayList<String> retVal = new ArrayList<String>();
|
||||
for (ValueSetExpansionContainsComponent next : theContains) {
|
||||
|
|
|
@ -24,6 +24,7 @@ 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.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
||||
|
@ -186,7 +187,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must not be populated"));
|
||||
}
|
||||
|
||||
|
@ -209,7 +210,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must be populated"));
|
||||
}
|
||||
|
||||
|
@ -232,7 +233,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
|||
try {
|
||||
myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("ID must be populated"));
|
||||
}
|
||||
|
||||
|
|
|
@ -382,6 +382,42 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Per a message on the mailing list
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithPostDoesntUpdate() throws Exception {
|
||||
|
||||
// First bundle (name is Joshua)
|
||||
|
||||
String input = IOUtils.toString(getClass().getResource("/dstu3-post1.xml"), StandardCharsets.UTF_8);
|
||||
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||
Bundle response = mySystemDao.transaction(mySrd, request);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
assertEquals(1, response.getEntry().size());
|
||||
assertEquals("201 Created", response.getEntry().get(0).getResponse().getStatus());
|
||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||
String id = response.getEntry().get(0).getResponse().getLocation();
|
||||
|
||||
// Now the second (name is Adam, shouldn't get used)
|
||||
|
||||
input = IOUtils.toString(getClass().getResource("/dstu3-post2.xml"), StandardCharsets.UTF_8);
|
||||
request = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||
response = mySystemDao.transaction(mySrd, request);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
assertEquals(1, response.getEntry().size());
|
||||
assertEquals("200 OK", response.getEntry().get(0).getResponse().getStatus());
|
||||
assertEquals("1", response.getEntry().get(0).getResponse().getEtag());
|
||||
String id2 = response.getEntry().get(0).getResponse().getLocation();
|
||||
assertEquals(id, id2);
|
||||
|
||||
Patient patient = myPatientDao.read(new IdType(id), mySrd);
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
|
||||
assertEquals("Joshua", patient.getNameFirstRep().getGivenAsSingleString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateInlineMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateInlineMatchUrlWithOneMatch";
|
||||
|
|
|
@ -60,7 +60,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<RuntimeSearchParam> getAllSearchParams(String theResourceName) {
|
||||
public Map<String, Map<String, RuntimeSearchParam>> getActiveSearchParams() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2556,4 +2556,61 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOnNoId() throws Exception {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/QuestionnaireResponse/$validate");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(get);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertThat(responseString, containsString("No resource supplied for $validate operation"));
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* From a Skype message from Brian Postlethwaite
|
||||
*/
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithNoIdForCreate() throws Exception {
|
||||
|
||||
String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"create\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"<div>!-- populated from the rendered HTML below --></div>\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\",\"group\":{\"question\":[{\"linkId\":\"d94b4f57-1ca0-4d65-acba-8bd9a3926c8c\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has a valid Medicare or DVA entitlement card\"},{\"linkId\":\"0cbe66db-ff12-473a-940e-4672fb82de44\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has received a MedsCheck, Diabetes MedsCheck, Home Medicines Review (HMR) otr Restidential Medication Management Review (RMMR) in the past 12 months\"},{\"linkId\":\"35790cfd-2d98-4721-963e-9663e1897a17\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient is living at home in a community setting\"},{\"linkId\":\"3ccc8304-76cd-41ff-9360-2c8755590bae\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has been recently diagnosed with type 3 diabetes (in the last 12 months) AND is unable to gain timely access to existing diabetes education or health services in the community OR \"},{\"linkId\":\"b05f6f09-49ec-40f9-a889-9a3fdff9e0da\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has type 2 diabetes , is less than ideally controlled AND is unable to gain timely access to existing diabetes education or health services in their community \"},{\"linkId\":\"4a777f56-800d-4e0b-a9c3-e929832adb5b\",\"answer\":[{\"valueBoolean\":false,\"group\":[{\"linkId\":\"95bbc904-149e-427f-88a4-7f6c8ab186fa\",\"question\":[{\"linkId\":\"f0acea9e-716c-4fce-b7a2-aad59de9d136\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Patient has had an Acute or Adverse Event\"},{\"linkId\":\"e1629159-6dea-4295-a93e-e7c2829ce180\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Exacerbation of a Chronic Disease or Condition\"},{\"linkId\":\"2ce526fa-edaa-44b3-8d5a-6e97f6379ce8\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"New Diagnosis\"},{\"linkId\":\"9d6ffa9f-0110-418c-9ed0-f04910fda2ed\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Recent hospital admission (<3 months)\"},{\"linkId\":\"d2803ff7-25f7-4c7b-ab92-356c49910478\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Major change to regular medication regime\"},{\"linkId\":\"b34af32d-c69d-4d44-889f-5b6d420a7d08\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Suspected non-adherence to the patient's medication regime \"},{\"linkId\":\"74bad553-c273-41e6-8647-22b860430bc2\",\"answer\":[],\"text\":\"Other\"}]}]}],\"text\":\"The patient has experienced one or more of the following recent significant medical events\"},{\"linkId\":\"ecbf4e5a-d4d1-43eb-9f43-0c0e35fc09c7\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The Pharmacist has obtained patient consent to take part in the MedsCheck Service or Diabetes MedsCheck Service and share information obtained during the services with other nominated members of the patients healthcare team (such as their GP, diabetes educator) if required\"},{\"linkId\":\"8ef66774-43b0-4190-873f-cfbb6e980aa9\",\"answer\":[],\"text\":\"Question\"}]}}}]}";
|
||||
HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true");
|
||||
post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertThat(responseString, containsString("No issues detected"));
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* From a Skype message from Brian Postlethwaite
|
||||
*/
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithNoIdForUpdate() throws Exception {
|
||||
|
||||
String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"update\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"<div>!-- populated from the rendered HTML below --></div>\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\",\"group\":{\"question\":[{\"linkId\":\"d94b4f57-1ca0-4d65-acba-8bd9a3926c8c\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has a valid Medicare or DVA entitlement card\"},{\"linkId\":\"0cbe66db-ff12-473a-940e-4672fb82de44\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has received a MedsCheck, Diabetes MedsCheck, Home Medicines Review (HMR) otr Restidential Medication Management Review (RMMR) in the past 12 months\"},{\"linkId\":\"35790cfd-2d98-4721-963e-9663e1897a17\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient is living at home in a community setting\"},{\"linkId\":\"3ccc8304-76cd-41ff-9360-2c8755590bae\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has been recently diagnosed with type 3 diabetes (in the last 12 months) AND is unable to gain timely access to existing diabetes education or health services in the community OR \"},{\"linkId\":\"b05f6f09-49ec-40f9-a889-9a3fdff9e0da\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has type 2 diabetes , is less than ideally controlled AND is unable to gain timely access to existing diabetes education or health services in their community \"},{\"linkId\":\"4a777f56-800d-4e0b-a9c3-e929832adb5b\",\"answer\":[{\"valueBoolean\":false,\"group\":[{\"linkId\":\"95bbc904-149e-427f-88a4-7f6c8ab186fa\",\"question\":[{\"linkId\":\"f0acea9e-716c-4fce-b7a2-aad59de9d136\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Patient has had an Acute or Adverse Event\"},{\"linkId\":\"e1629159-6dea-4295-a93e-e7c2829ce180\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Exacerbation of a Chronic Disease or Condition\"},{\"linkId\":\"2ce526fa-edaa-44b3-8d5a-6e97f6379ce8\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"New Diagnosis\"},{\"linkId\":\"9d6ffa9f-0110-418c-9ed0-f04910fda2ed\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Recent hospital admission (<3 months)\"},{\"linkId\":\"d2803ff7-25f7-4c7b-ab92-356c49910478\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Major change to regular medication regime\"},{\"linkId\":\"b34af32d-c69d-4d44-889f-5b6d420a7d08\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Suspected non-adherence to the patient's medication regime \"},{\"linkId\":\"74bad553-c273-41e6-8647-22b860430bc2\",\"answer\":[],\"text\":\"Other\"}]}]}],\"text\":\"The patient has experienced one or more of the following recent significant medical events\"},{\"linkId\":\"ecbf4e5a-d4d1-43eb-9f43-0c0e35fc09c7\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The Pharmacist has obtained patient consent to take part in the MedsCheck Service or Diabetes MedsCheck Service and share information obtained during the services with other nominated members of the patients healthcare team (such as their GP, diabetes educator) if required\"},{\"linkId\":\"8ef66774-43b0-4190-873f-cfbb6e980aa9\",\"answer\":[],\"text\":\"Question\"}]}}}]}";
|
||||
HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true");
|
||||
post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertThat(responseString, containsString("Resource has no ID"));
|
||||
assertEquals(422, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -139,7 +140,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
get.addHeader("Accept", "application/xml, text/html");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
String response = IOUtils.toString(http.getEntity().getContent());
|
||||
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
assertThat(response, (containsString("_format=json")));
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
|
@ -167,7 +168,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
get.addHeader("Accept", "application/xml+fhir");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
String response = IOUtils.toString(http.getEntity().getContent());
|
||||
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
assertThat(response, not(containsString("_format")));
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
|
@ -216,7 +217,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
|
||||
Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
|
||||
|
@ -246,7 +247,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'context' must be provided"));
|
||||
} finally {
|
||||
|
@ -257,7 +258,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'searchParam' must be provided"));
|
||||
} finally {
|
||||
|
@ -268,7 +269,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'text' must be provided"));
|
||||
} finally {
|
||||
|
@ -286,7 +287,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
@ -295,7 +296,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
public void testTransactionFromBundle2() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
|
@ -311,7 +312,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
*/
|
||||
|
||||
bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
bundle = IOUtils.toString(bundleRes);
|
||||
bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
|
@ -335,7 +336,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
public void testTransactionFromBundle3() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/grahame-transaction.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
@ -343,7 +344,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle4() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
Bundle bundleResp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
|
@ -358,7 +359,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle5() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle2.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
try {
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
fail();
|
||||
|
@ -372,7 +373,7 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
// try {
|
||||
// fail();
|
||||
|
@ -427,5 +428,18 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
|||
assertEquals(0, respSub.getEntry().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarkResourcesForReindexing() throws Exception {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/$mark-all-resources-for-reindexing");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(http);;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
||||
|
@ -35,6 +36,7 @@ import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.gclient.ReferenceClientParam;
|
||||
import ca.uhn.fhir.rest.gclient.TokenClientParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
@ -58,7 +60,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
public void saveCreateSearchParamInvalidWithMissingStatus() throws IOException {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setCode("foo");
|
||||
sp.setXpath("Patient.gender");
|
||||
sp.setExpression("Patient.gender");
|
||||
sp.setXpathUsage(XPathUsageType.NORMAL);
|
||||
sp.setTitle("Foo Param");
|
||||
|
||||
|
@ -66,10 +68,59 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
ourClient.create().resource(sp).execute();
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("HTTP 422 Unprocessable Entity: Resource.status is missing or invalid: null", e.getMessage());
|
||||
assertEquals("HTTP 422 Unprocessable Entity: SearchParameter.status is missing or invalid: null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchForExtension() {
|
||||
SearchParameter eyeColourSp = new SearchParameter();
|
||||
eyeColourSp.addBase("Patient");
|
||||
eyeColourSp.setCode("eyecolour");
|
||||
eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
eyeColourSp.setTitle("Eye Colour");
|
||||
eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')");
|
||||
eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(eyeColourSp));
|
||||
|
||||
ourClient
|
||||
.create()
|
||||
.resource(eyeColourSp)
|
||||
.execute();
|
||||
|
||||
// mySearchParamRegsitry.forceRefresh();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setActive(true);
|
||||
p1.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("blue"));
|
||||
IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless();
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p1));
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.setActive(true);
|
||||
p2.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("green"));
|
||||
IIdType p2id = myPatientDao.create(p2).getId().toUnqualifiedVersionless();
|
||||
|
||||
Bundle bundle = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(new TokenClientParam("eyecolour").exactly().code("blue"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
|
||||
|
||||
List<String> foundResources = toUnqualifiedVersionlessIdValues(bundle);
|
||||
assertThat(foundResources, contains(p1id.getValue()));
|
||||
|
||||
}
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderCustomSearchParamDstu3Test.class);
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void beforeResetConfig() {
|
||||
|
@ -97,20 +148,22 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
|
||||
// Add a custom search parameter
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
||||
// Disable an existing parameter
|
||||
fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("gender");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("Gender");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.RETIRED);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
@ -149,20 +202,22 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
|
||||
// Add a custom search parameter
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
||||
// Disable an existing parameter
|
||||
fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("gender");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("Gender");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.RETIRED);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
@ -203,10 +258,11 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
public void testSearchWithCustomParam() {
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
@ -232,6 +288,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
.where(new TokenClientParam("foo").exactly().code("male"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
foundResources = toUnqualifiedVersionlessIdValues(result);
|
||||
assertThat(foundResources, contains(patId.getValue()));
|
||||
|
||||
|
@ -253,10 +310,11 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
assertEquals(BaseHapiFhirDao.INDEX_STATUS_INDEXED, res.getIndexStatus().longValue());
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Patient.gender");
|
||||
fooSp.setExpression("Patient.gender");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
@ -273,10 +331,11 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
public void testSearchQualifiedWithCustomReferenceParam() {
|
||||
|
||||
SearchParameter fooSp = new SearchParameter();
|
||||
fooSp.addBase("Patient");
|
||||
fooSp.setCode("foo");
|
||||
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.REFERENCE);
|
||||
fooSp.setTitle("FOO SP");
|
||||
fooSp.setXpath("Observation.subject");
|
||||
fooSp.setExpression("Observation.subject");
|
||||
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
|
|
@ -149,7 +149,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@After
|
||||
public void after() throws Exception {
|
||||
super.after();
|
||||
|
||||
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
||||
}
|
||||
|
@ -160,15 +160,14 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
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);
|
||||
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
private ArrayList<IBaseResource> genResourcesOfType(Bundle theRes, Class<? extends IBaseResource> theClass) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
for (BundleEntryComponent next : theRes.getEntry()) {
|
||||
|
@ -197,7 +196,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
List<Extension> exts = basic.getExtensionsByUrl("http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/DateID");
|
||||
assertEquals(1, exts.size());
|
||||
}
|
||||
|
||||
|
||||
private List<String> searchAndReturnUnqualifiedIdValues(String uri) throws IOException, ClientProtocolException {
|
||||
List<String> ids;
|
||||
HttpGet get = new HttpGet(uri);
|
||||
|
@ -339,9 +338,9 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
Binary binary = new Binary();
|
||||
binary.setContent(arr);
|
||||
binary.setContentType("dansk");
|
||||
|
||||
|
||||
IIdType resource = ourClient.create().resource(binary).execute().getId();
|
||||
|
||||
|
||||
Binary fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
|
||||
assertEquals("1", fromDB.getIdElement().getVersionIdPart());
|
||||
|
||||
|
@ -355,7 +354,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
} finally {
|
||||
IOUtils.closeQuietly(resp);
|
||||
}
|
||||
|
||||
|
||||
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
|
||||
assertEquals("2", fromDB.getIdElement().getVersionIdPart());
|
||||
|
||||
|
@ -370,12 +369,12 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
} finally {
|
||||
IOUtils.closeQuietly(resp);
|
||||
}
|
||||
|
||||
|
||||
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
|
||||
assertEquals("3", fromDB.getIdElement().getVersionIdPart());
|
||||
|
||||
// Now an update with the wrong ID in the body
|
||||
|
||||
|
||||
arr[0] = 4;
|
||||
binary.setId("");
|
||||
encoded = myFhirCtx.newJsonParser().encodeResourceToString(binary);
|
||||
|
@ -387,7 +386,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
} finally {
|
||||
IOUtils.closeQuietly(resp);
|
||||
}
|
||||
|
||||
|
||||
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
|
||||
assertEquals("3", fromDB.getIdElement().getVersionIdPart());
|
||||
|
||||
|
@ -674,7 +673,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
String encoded = myFhirCtx.newXmlParser().encodeResourceToString(response);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString(
|
||||
"<issue><severity value=\"information\"/><code value=\"informational\"/><diagnostics value=\"Successfully deleted Patient?identifier=testDeleteConditionalMultiple resource(s) in 2ms\"/></issue>"));
|
||||
"<issue><severity value=\"information\"/><code value=\"informational\"/><diagnostics value=\"Successfully deleted 2 resource(s) in "));
|
||||
try {
|
||||
ourClient.read().resource("Patient").withId(id1).execute();
|
||||
fail();
|
||||
|
@ -726,7 +725,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
* Test for #345
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteNormal() throws IOException {
|
||||
public void testDeleteNormal() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("FAM");
|
||||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||
|
@ -743,6 +742,17 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteReturnsOperationOutcome() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("FAM");
|
||||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
IBaseOperationOutcome resp = ourClient.delete().resourceById(id).execute();
|
||||
OperationOutcome oo = (OperationOutcome) resp;
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Successfully deleted 1 resource(s) in "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteResourceConditional1() throws IOException {
|
||||
String methodName = "testDeleteResourceConditional1";
|
||||
|
@ -768,6 +778,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
response = ourHttpClient.execute(delete);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, resp);
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Successfully deleted 1 resource(s) in "));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
@ -777,6 +791,24 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
try {
|
||||
ourLog.info(response.toString());
|
||||
assertEquals(Constants.STATUS_HTTP_410_GONE, response.getStatusLine().getStatusCode());
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, resp);
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Resource was deleted at"));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
// Delete should now have no matches
|
||||
|
||||
delete = new HttpDelete(ourServerBase + "/Patient?name=" + methodName);
|
||||
response = ourHttpClient.execute(delete);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, resp);
|
||||
assertThat(oo.getIssueFirstRep().getDiagnostics(), startsWith("Unable to find resource matching URL \"Patient?name=testDeleteResourceConditional1\". Deletion failed."));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
@ -1781,7 +1813,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
ourLog.info("Response: {}", respString);
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, respString);
|
||||
assertEquals("Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"AAA\" does not match URL ID of \"" + id.getIdPart() + "\"", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals(
|
||||
"Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"AAA\" does not match URL ID of \""
|
||||
+ id.getIdPart() + "\"",
|
||||
oo.getIssue().get(0).getDiagnostics());
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
@ -1809,12 +1844,11 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@Test
|
||||
public void testIncludeWithExternalReferences() {
|
||||
myDaoConfig.setAllowExternalReferences(true);
|
||||
|
||||
|
||||
Patient p = new Patient();
|
||||
p.getManagingOrganization().setReference("http://example.com/Organization/123");
|
||||
ourClient.create().resource(p).execute();
|
||||
|
||||
|
||||
|
||||
Bundle b = ourClient.search().forResource("Patient").include(Patient.INCLUDE_ORGANIZATION).returnBundle(Bundle.class).execute();
|
||||
assertEquals(1, b.getEntry().size());
|
||||
}
|
||||
|
@ -1834,7 +1868,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMetadataSuperParamsAreIncluded() throws IOException {
|
||||
StructureDefinition p = new StructureDefinition();
|
||||
|
@ -1843,12 +1876,12 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
Bundle resp = ourClient
|
||||
.search()
|
||||
.forResource(StructureDefinition.class)
|
||||
.where(StructureDefinition.URL.matches().value("http://example.com/foo"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
.search()
|
||||
.forResource(StructureDefinition.class)
|
||||
.where(StructureDefinition.URL.matches().value("http://example.com/foo"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
assertEquals(1, resp.getTotal());
|
||||
}
|
||||
|
||||
|
@ -2101,9 +2134,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
String input = IOUtils.toString(getClass().getResourceAsStream("/two_questionnaires.json"), StandardCharsets.UTF_8);
|
||||
String respString = ourClient.transaction().withBundle(input).prettyPrint().execute();
|
||||
ourLog.info(respString);
|
||||
|
||||
ourHttpClient.execute(new HttpGet("http://localhost:" + ourPort + "/QuestionnaireResponse?patient=QR3295&questionnaire=profile&_sort:desc=authored&_count=5&_include=QuestionnaireResponse:questionnaire&_include=QuestionnaireResponse:subject"));
|
||||
// Bundle bundle =
|
||||
|
||||
ourHttpClient.execute(new HttpGet("http://localhost:" + ourPort
|
||||
+ "/QuestionnaireResponse?patient=QR3295&questionnaire=profile&_sort:desc=authored&_count=5&_include=QuestionnaireResponse:questionnaire&_include=QuestionnaireResponse:subject"));
|
||||
// Bundle bundle =
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2284,14 +2318,14 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(BaseResource.RES_ID.exactly().systemAndValues(null, id1.getIdPart(), id2.getIdPart()))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(BaseResource.RES_ID.exactly().systemAndValues(null, id1.getIdPart(), id2.getIdPart()))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
assertThat(toUnqualifiedVersionlessIds(found), empty());
|
||||
|
||||
|
||||
found = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
|
@ -2319,14 +2353,14 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
.execute();
|
||||
|
||||
assertThat(toUnqualifiedVersionlessIds(found), containsInAnyOrder(id1));
|
||||
|
||||
|
||||
found = ourClient
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(BaseResource.RES_ID.exactly().codes(Arrays.asList(id1.getIdPart(), id2.getIdPart(), "FOOOOO")))
|
||||
.and(BaseResource.RES_ID.exactly().code(id1.getIdPart()))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(BaseResource.RES_ID.exactly().codes(Arrays.asList(id1.getIdPart(), id2.getIdPart(), "FOOOOO")))
|
||||
.and(BaseResource.RES_ID.exactly().code(id1.getIdPart()))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
assertThat(toUnqualifiedVersionlessIds(found), containsInAnyOrder(id1));
|
||||
|
||||
|
@ -3445,7 +3479,9 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
ourLog.info(responseString);
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
|
||||
assertEquals("Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"333\" does not match URL ID of \"A2\"", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals(
|
||||
"Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"333\" does not match URL ID of \"A2\"",
|
||||
oo.getIssue().get(0).getDiagnostics());
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
|
@ -181,5 +183,63 @@ public class ResourceProviderQuestionnaireResponseDstu3Test extends BaseResource
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateOnNoId() throws Exception {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/QuestionnaireResponse/$validate");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(get);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertThat(responseString, containsString("No resource supplied for $validate operation"));
|
||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* From a Skype message from Brian Postlethwaite
|
||||
*/
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithNoIdForCreate() throws Exception {
|
||||
|
||||
String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"create\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">!-- populated from the rendered HTML below --></div>\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\"}}]}";
|
||||
HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true");
|
||||
post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* From a Skype message from Brian Postlethwaite
|
||||
*/
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithNoIdForUpdate() throws Exception {
|
||||
|
||||
String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"update\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">!-- populated from the rendered HTML below --></div>\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\"}}]}";
|
||||
HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true");
|
||||
post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON));
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info("Response: {}", responseString);
|
||||
assertThat(responseString, containsString("Resource has no ID"));
|
||||
assertEquals(422, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(req);
|
||||
try {
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent());
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(encoded);
|
||||
|
||||
assertThat(encoded, containsString("transaction-response"));
|
||||
|
@ -162,7 +162,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(req);
|
||||
try {
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent());
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(encoded);
|
||||
|
||||
assertThat(encoded, containsString("transaction-response"));
|
||||
|
@ -271,14 +271,14 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
try {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/questionnaire-sdc-profile-example-ussg-fht.xml");
|
||||
String bundleStr = IOUtils.toString(bundleRes);
|
||||
String bundleStr = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
|
||||
HttpPost req = new HttpPost(ourServerBase);
|
||||
req.setEntity(new StringEntity(bundleStr, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
|
||||
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(req);
|
||||
try {
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent());
|
||||
String encoded = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(encoded);
|
||||
|
||||
//@formatter:off
|
||||
|
@ -314,7 +314,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
|
||||
try {
|
||||
String response = IOUtils.toString(http.getEntity().getContent());
|
||||
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("_format=json"));
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
|
@ -342,7 +342,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
get.addHeader("Accept", "application/xml+fhir");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
String response = IOUtils.toString(http.getEntity().getContent());
|
||||
String response = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
assertThat(response, not(containsString("_format")));
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
|
@ -373,7 +373,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
HttpGet get = new HttpGet(ourServerBase + "/$mark-all-resources-for-reindexing");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
|
@ -404,7 +404,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
|
||||
Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
|
||||
|
@ -434,7 +434,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'context' must be provided"));
|
||||
} finally {
|
||||
|
@ -445,7 +445,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'searchParam' must be provided"));
|
||||
} finally {
|
||||
|
@ -456,7 +456,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(400, http.getStatusLine().getStatusCode());
|
||||
String output = IOUtils.toString(http.getEntity().getContent());
|
||||
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(output);
|
||||
assertThat(output, containsString("Parameter 'text' must be provided"));
|
||||
} finally {
|
||||
|
@ -500,7 +500,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
public void testTransactionFromBundle2() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
|
@ -516,7 +516,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
*/
|
||||
|
||||
bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/transaction_link_patient_eve_temp.xml");
|
||||
bundle = IOUtils.toString(bundleRes);
|
||||
bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
|
||||
|
@ -540,7 +540,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
public void testTransactionFromBundle3() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/grahame-transaction.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle4() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/simone_bundle.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
Bundle bundleResp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
|
@ -563,7 +563,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle5() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/simone_bundle2.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
try {
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
fail();
|
||||
|
@ -577,7 +577,7 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
|||
@Test
|
||||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu3Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String bundle = IOUtils.toString(bundleRes, StandardCharsets.UTF_8);
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
// try {
|
||||
// fail();
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<type value="transaction"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<id value="ID613876"/>
|
||||
<identifier>
|
||||
<value value="ID613876"/>
|
||||
</identifier>
|
||||
<name>
|
||||
<given value="Joshua"/>
|
||||
</name>
|
||||
</Patient>
|
||||
</resource>
|
||||
<request>
|
||||
<method value="POST"/>
|
||||
<url value="Patient/ID613876"/>
|
||||
<ifNoneExist value="identifier=ID613876"/>
|
||||
</request>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<type value="transaction"/>
|
||||
<entry>
|
||||
<resource>
|
||||
<Patient>
|
||||
<id value="ID613876"/>
|
||||
<identifier>
|
||||
<value value="ID613876"/>
|
||||
</identifier>
|
||||
<name>
|
||||
<given value="Adam"/>
|
||||
</name>
|
||||
</Patient>
|
||||
</resource>
|
||||
<request>
|
||||
<method value="POST"/>
|
||||
<url value="Patient/ID613876"/>
|
||||
<ifNoneExist value="identifier=ID613876"/>
|
||||
</request>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"resourceType": "CodeSystem",
|
||||
"id": "22472",
|
||||
"meta": {
|
||||
"versionId": "3",
|
||||
"lastUpdated": "2017-01-27T10:53:39.457-05:00"
|
||||
},
|
||||
"url": "xvalue://dedalus.eu/mci/CodeSystem/AddressUse",
|
||||
"name": "AddressUse",
|
||||
"status": "active",
|
||||
"publisher": "x1v1-mci",
|
||||
"date": "2016-04-07",
|
||||
"description": "AddressUse",
|
||||
"caseSensitive": true,
|
||||
"compositional": false,
|
||||
"versionNeeded": false,
|
||||
"content": "complete",
|
||||
"concept": {
|
||||
"code": "work",
|
||||
"display": "Work",
|
||||
"definition": "An office address. First choice for business related contacts during business hours.",
|
||||
"designation": {
|
||||
"language": "IT",
|
||||
"value": "Lavoro"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -575,6 +575,11 @@ public class SearchDstu2Test {
|
|||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[*.java]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
@ -6,33 +6,33 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
* Copyright (c) 2011+, HL7, Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -72,66 +72,67 @@ import org.hl7.fhir.utilities.Utilities;
|
|||
|
||||
public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||
|
||||
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private IWorkerContext context;
|
||||
private IWorkerContext context;
|
||||
private boolean canBeHeirarchy = true;
|
||||
private Set<String> excludeKeys = new HashSet<String>();
|
||||
private Set<String> excludeKeys = new HashSet<String>();
|
||||
private Set<String> excludeSystems = new HashSet<String>();
|
||||
private ValueSetExpanderFactory factory;
|
||||
private ValueSet focus;
|
||||
private int maxExpansionSize = 500;
|
||||
private ValueSetExpanderFactory factory;
|
||||
private ValueSet focus;
|
||||
private int maxExpansionSize = 500;
|
||||
|
||||
private int total;
|
||||
private int total;
|
||||
|
||||
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.factory = factory;
|
||||
}
|
||||
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
||||
maxExpansionSize = theMaxExpansionSize;
|
||||
}
|
||||
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
||||
maxExpansionSize = theMaxExpansionSize;
|
||||
}
|
||||
|
||||
|
||||
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, ExpansionProfile profile, boolean isAbstract, boolean inactive, List<ValueSet> filters) {
|
||||
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations,
|
||||
ExpansionProfile profile, boolean isAbstract, boolean inactive, List<ValueSet> filters) {
|
||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
||||
return null;
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(system);
|
||||
n.setCode(code);
|
||||
if (isAbstract)
|
||||
n.setSystem(system);
|
||||
n.setCode(code);
|
||||
if (isAbstract)
|
||||
n.setAbstract(true);
|
||||
if (inactive)
|
||||
n.setInactive(true);
|
||||
|
||||
|
||||
if (profile.getIncludeDesignations() && designations != null) {
|
||||
for (ConceptDefinitionDesignationComponent t : designations) {
|
||||
ToolingExtensions.addLanguageTranslation(n, t.getLanguage(), t.getValue());
|
||||
ToolingExtensions.addLanguageTranslation(n, t.getLanguage(), t.getValue());
|
||||
}
|
||||
}
|
||||
ConceptDefinitionDesignationComponent t = profile.hasLanguage() ? getMatchingLang(designations, profile.getLanguage()) : null;
|
||||
if (t == null)
|
||||
n.setDisplay(display);
|
||||
n.setDisplay(display);
|
||||
else
|
||||
n.setDisplay(t.getValue());
|
||||
|
||||
String s = key(n);
|
||||
if (map.containsKey(s) || excludeKeys.contains(s)) {
|
||||
canBeHeirarchy = false;
|
||||
} else {
|
||||
codes.add(n);
|
||||
map.put(s, n);
|
||||
}
|
||||
if (canBeHeirarchy && parent != null) {
|
||||
parent.getContains().add(n);
|
||||
} else {
|
||||
roots.add(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
String s = key(n);
|
||||
if (map.containsKey(s) || excludeKeys.contains(s)) {
|
||||
canBeHeirarchy = false;
|
||||
} else {
|
||||
codes.add(n);
|
||||
map.put(s, n);
|
||||
total++;
|
||||
}
|
||||
if (canBeHeirarchy && parent != null) {
|
||||
parent.getContains().add(n);
|
||||
} else {
|
||||
roots.add(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
private boolean filterContainsCode(List<ValueSet> filters, String system, String code) {
|
||||
for (ValueSet vse : filters)
|
||||
|
@ -160,93 +161,92 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filters) throws FHIRException {
|
||||
if (!CodeSystemUtilities.isDeprecated(cs, def)) {
|
||||
ValueSetExpansionContainsComponent np = null;
|
||||
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filters)
|
||||
throws FHIRException {
|
||||
if (!CodeSystemUtilities.isDeprecated(cs, def)) {
|
||||
ValueSetExpansionContainsComponent np = null;
|
||||
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
||||
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
||||
if (canBeHeirarchy || !abs)
|
||||
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), profile, abs, inc, filters);
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(cs, system, c, np, profile, filters);
|
||||
} else
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(cs, system, c, null, profile, filters);
|
||||
} else
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(cs, system, c, null, profile, filters);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile, List<ValueSet> filters) throws ETooCostly {
|
||||
if (expand.getContains().size() > maxExpansionSize)
|
||||
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
||||
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||
params.add(p);
|
||||
}
|
||||
if (expand.getContains().size() > maxExpansionSize)
|
||||
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
||||
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||
params.add(p);
|
||||
}
|
||||
|
||||
copyImportContains(expand.getContains(), null, profile, filters);
|
||||
|
||||
total = expand.getTotal();
|
||||
}
|
||||
}
|
||||
|
||||
private void excludeCode(String theSystem, String theCode) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(theSystem);
|
||||
n.setCode(theCode);
|
||||
String s = key(n);
|
||||
excludeKeys.add(s);
|
||||
}
|
||||
private void excludeCode(String theSystem, String theCode) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(theSystem);
|
||||
n.setCode(theCode);
|
||||
String s = key(n);
|
||||
excludeKeys.add(s);
|
||||
}
|
||||
|
||||
private void excludeCodes(ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params) throws TerminologyServiceException {
|
||||
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
||||
excludeSystems.add(exc.getSystem());
|
||||
}
|
||||
private void excludeCodes(ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params) throws TerminologyServiceException {
|
||||
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
||||
excludeSystems.add(exc.getSystem());
|
||||
}
|
||||
|
||||
if (exc.hasValueSet())
|
||||
throw new Error("Processing Value set references in exclude is not yet done");
|
||||
// importValueSet(imp.getValue(), params, profile);
|
||||
// importValueSet(imp.getValue(), params, profile);
|
||||
|
||||
CodeSystem cs = context.fetchCodeSystem(exc.getSystem());
|
||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem())) {
|
||||
excludeCodes(context.expandVS(exc, false), params);
|
||||
return;
|
||||
}
|
||||
CodeSystem cs = context.fetchCodeSystem(exc.getSystem());
|
||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem())) {
|
||||
excludeCodes(context.expandVS(exc, false), params);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ConceptReferenceComponent c : exc.getConcept()) {
|
||||
excludeCode(exc.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
if (exc.getFilter().size() > 0)
|
||||
throw new NotImplementedException("not done yet");
|
||||
}
|
||||
for (ConceptReferenceComponent c : exc.getConcept()) {
|
||||
excludeCode(exc.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(c.getSystem(), c.getCode());
|
||||
}
|
||||
}
|
||||
if (exc.getFilter().size() > 0)
|
||||
throw new NotImplementedException("not done yet");
|
||||
}
|
||||
|
||||
private boolean existsInParams(List<ValueSetExpansionParameterComponent> params, String name, Type value) {
|
||||
for (ValueSetExpansionParameterComponent p : params) {
|
||||
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(c.getSystem(), c.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
private boolean existsInParams(List<ValueSetExpansionParameterComponent> params, String name, Type value) {
|
||||
for (ValueSetExpansionParameterComponent p : params) {
|
||||
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpansionOutcome expand(ValueSet source, ExpansionProfile profile) {
|
||||
|
||||
if (profile == null)
|
||||
profile = makeDefaultExpansion();
|
||||
try {
|
||||
focus = source.copy();
|
||||
focus.setExpansion(new ValueSet.ValueSetExpansionComponent());
|
||||
focus.getExpansion().setTimestampElement(DateTimeType.now());
|
||||
focus.getExpansion().setIdentifier(Factory.createUUID());
|
||||
try {
|
||||
focus = source.copy();
|
||||
focus.setExpansion(new ValueSet.ValueSetExpansionComponent());
|
||||
focus.getExpansion().setTimestampElement(DateTimeType.now());
|
||||
focus.getExpansion().setIdentifier(Factory.createUUID());
|
||||
if (!profile.getUrl().startsWith("urn:uuid:"))
|
||||
focus.getExpansion().addParameter().setName("profile").setValue(new UriType(profile.getUrl()));
|
||||
|
||||
if (source.hasCompose())
|
||||
if (source.hasCompose())
|
||||
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), profile);
|
||||
|
||||
if (canBeHeirarchy) {
|
||||
|
@ -254,38 +254,38 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
focus.getExpansion().getContains().add(c);
|
||||
}
|
||||
} else {
|
||||
for (ValueSetExpansionContainsComponent c : codes) {
|
||||
for (ValueSetExpansionContainsComponent c : codes) {
|
||||
if (map.containsKey(key(c)) && !c.getAbstract()) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
|
||||
focus.getExpansion().getContains().add(c);
|
||||
focus.getExpansion().getContains().add(c);
|
||||
c.getContains().clear(); // make sure any heirarchy is wiped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (total > 0) {
|
||||
focus.getExpansion().setTotal(total);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (total > 0) {
|
||||
focus.getExpansion().setTotal(total);
|
||||
}
|
||||
|
||||
return new ValueSetExpansionOutcome(focus);
|
||||
} catch (RuntimeException e) {
|
||||
// TODO: we should put something more specific instead of just Exception below, since
|
||||
// it swallows bugs.. what would be expected to be caught there?
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
// TODO: we should put something more specific instead of just Exception below, since
|
||||
// it swallows bugs.. what would be expected to be caught there?
|
||||
throw e;
|
||||
} catch (NoTerminologyServiceException e) {
|
||||
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
||||
// that might fail too, but it might not, later.
|
||||
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.NOSERVICE);
|
||||
} catch (Exception e) {
|
||||
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
||||
// that might fail too, but it might not, later.
|
||||
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
||||
// that might fail too, but it might not, later.
|
||||
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
private ExpansionProfile makeDefaultExpansion() {
|
||||
ExpansionProfile res = new ExpansionProfile();
|
||||
res.setUrl("urn:uuid:"+UUID.randomUUID().toString().toLowerCase());
|
||||
res.setExcludeNested(true);
|
||||
private ExpansionProfile makeDefaultExpansion() {
|
||||
ExpansionProfile res = new ExpansionProfile();
|
||||
res.setUrl("urn:uuid:" + UUID.randomUUID().toString().toLowerCase());
|
||||
res.setExcludeNested(true);
|
||||
res.setIncludeDesignations(false);
|
||||
return res;
|
||||
}
|
||||
|
@ -296,68 +296,70 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
}
|
||||
}
|
||||
|
||||
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
|
||||
if (def == null)
|
||||
throw new TerminologyServiceException("Unable to find code '" + code + "' in code system " + cs.getUrl());
|
||||
return def.getDisplay();
|
||||
}
|
||||
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
|
||||
if (def == null)
|
||||
throw new TerminologyServiceException("Unable to find code '" + code + "' in code system " + cs.getUrl());
|
||||
return def.getDisplay();
|
||||
}
|
||||
|
||||
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> clist, String code) {
|
||||
for (ConceptDefinitionComponent c : clist) {
|
||||
if (code.equals(c.getCode()))
|
||||
return c;
|
||||
ConceptDefinitionComponent v = getConceptForCode(c.getConcept(), code);
|
||||
if (v != null)
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> clist, String code) {
|
||||
for (ConceptDefinitionComponent c : clist) {
|
||||
if (code.equals(c.getCode()))
|
||||
return c;
|
||||
ConceptDefinitionComponent v = getConceptForCode(c.getConcept(), code);
|
||||
if (v != null)
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCompose(ValueSetComposeComponent compose, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
||||
// Exclude comes first because we build up a map of things to exclude
|
||||
for (ConceptSetComponent inc : compose.getExclude())
|
||||
excludeCodes(inc, params);
|
||||
private void handleCompose(ValueSetComposeComponent compose, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile)
|
||||
throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
||||
// Exclude comes first because we build up a map of things to exclude
|
||||
for (ConceptSetComponent inc : compose.getExclude())
|
||||
excludeCodes(inc, params);
|
||||
canBeHeirarchy = !profile.getExcludeNested() && excludeKeys.isEmpty() && excludeSystems.isEmpty();
|
||||
boolean first = true;
|
||||
for (ConceptSetComponent inc : compose.getInclude()) {
|
||||
if (first == true)
|
||||
first = false;
|
||||
else
|
||||
canBeHeirarchy = false;
|
||||
boolean first = true;
|
||||
for (ConceptSetComponent inc : compose.getInclude()) {
|
||||
if (first == true)
|
||||
first = false;
|
||||
else
|
||||
canBeHeirarchy = false;
|
||||
includeCodes(inc, params, profile);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private ValueSet importValueSet(String value, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException {
|
||||
if (value == null)
|
||||
throw new TerminologyServiceException("unable to find value set with no identity");
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, value);
|
||||
if (vs == null)
|
||||
throw new TerminologyServiceException("Unable to find imported value set " + value);
|
||||
ValueSetExpansionOutcome vso = factory.getExpander().expand(vs, profile);
|
||||
private ValueSet importValueSet(String value, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile)
|
||||
throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException {
|
||||
if (value == null)
|
||||
throw new TerminologyServiceException("unable to find value set with no identity");
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, value);
|
||||
if (vs == null)
|
||||
throw new TerminologyServiceException("Unable to find imported value set " + value);
|
||||
ValueSetExpansionOutcome vso = factory.getExpander().expand(vs, profile);
|
||||
if (vso.getError() != null)
|
||||
throw new TerminologyServiceException("Unable to expand imported value set: "+vso.getError());
|
||||
if (vso.getService() != null)
|
||||
throw new TerminologyServiceException("Unable to expand imported value set "+value);
|
||||
if (vs.hasVersion())
|
||||
if (!existsInParams(params, "version", new UriType(vs.getUrl()+"|"+vs.getVersion())))
|
||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl()+"|"+vs.getVersion())));
|
||||
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
|
||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||
params.add(p);
|
||||
}
|
||||
throw new TerminologyServiceException("Unable to expand imported value set: " + vso.getError());
|
||||
if (vso.getService() != null)
|
||||
throw new TerminologyServiceException("Unable to expand imported value set " + value);
|
||||
if (vs.hasVersion())
|
||||
if (!existsInParams(params, "version", new UriType(vs.getUrl() + "|" + vs.getVersion())))
|
||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
|
||||
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
|
||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||
params.add(p);
|
||||
}
|
||||
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
|
||||
return vso.getValueset();
|
||||
return vso.getValueset();
|
||||
}
|
||||
|
||||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filter) {
|
||||
for (ValueSetExpansionContainsComponent c : list) {
|
||||
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), parent, null, profile, c.getAbstract(), c.getInactive(), filter);
|
||||
copyImportContains(c.getContains(), np, profile, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void includeCodes(ConceptSetComponent inc, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
||||
List<ValueSet> imports = new ArrayList<ValueSet>();
|
||||
|
@ -367,9 +369,9 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
if (!inc.hasSystem()) {
|
||||
if (imports.isEmpty()) // though this is not supposed to be the case
|
||||
return;
|
||||
ValueSet base = imports.get(0);
|
||||
ValueSet base = imports.get(0);
|
||||
imports.remove(0);
|
||||
copyImportContains(base.getExpansion().getContains(), null, profile, imports);
|
||||
copyImportContains(base.getExpansion().getContains(), null, profile, imports);
|
||||
} else {
|
||||
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(inc.getSystem())) {
|
||||
|
@ -379,15 +381,15 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
|
||||
if (cs == null) {
|
||||
if (context.isNoTerminologyServer())
|
||||
throw new NoTerminologyServiceException("unable to find code system "+inc.getSystem().toString());
|
||||
throw new NoTerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||
else
|
||||
throw new TerminologyServiceException("unable to find code system "+inc.getSystem().toString());
|
||||
throw new TerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||
}
|
||||
if (cs.getContent() != CodeSystemContentMode.COMPLETE)
|
||||
throw new TerminologyServiceException("Code system "+inc.getSystem().toString()+" is incomplete");
|
||||
throw new TerminologyServiceException("Code system " + inc.getSystem().toString() + " is incomplete");
|
||||
if (cs.hasVersion())
|
||||
if (!existsInParams(params, "version", new UriType(cs.getUrl()+"|"+cs.getVersion())))
|
||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl()+"|"+cs.getVersion())));
|
||||
if (!existsInParams(params, "version", new UriType(cs.getUrl() + "|" + cs.getVersion())))
|
||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl() + "|" + cs.getVersion())));
|
||||
|
||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||
// special case - add all the code system
|
||||
|
@ -399,7 +401,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
if (!inc.getConcept().isEmpty()) {
|
||||
canBeHeirarchy = false;
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), profile, false, CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
|
||||
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), profile, false,
|
||||
CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 1) {
|
||||
|
@ -412,13 +415,13 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
// special: all codes in the target code system under the value
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (def == null)
|
||||
throw new TerminologyServiceException("Code '"+fc.getValue()+"' not found in system '"+inc.getSystem()+"'");
|
||||
throw new TerminologyServiceException("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, profile, imports);
|
||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
||||
// special: all codes in the target code system under the value
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (def == null)
|
||||
throw new TerminologyServiceException("Code '"+fc.getValue()+"' not found in system '"+inc.getSystem()+"'");
|
||||
throw new TerminologyServiceException("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, profile, imports);
|
||||
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
||||
|
@ -428,7 +431,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
if (def != null) {
|
||||
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
||||
if (def.getDisplay().contains(fc.getValue())) {
|
||||
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), profile, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def), imports);
|
||||
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), profile, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||
imports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,12 +453,12 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
return res;
|
||||
}
|
||||
|
||||
private String key(String uri, String code) {
|
||||
return "{" + uri + "}" + code;
|
||||
}
|
||||
private String key(String uri, String code) {
|
||||
return "{" + uri + "}" + code;
|
||||
}
|
||||
|
||||
private String key(ValueSetExpansionContainsComponent c) {
|
||||
return key(c.getSystem(), c.getCode());
|
||||
}
|
||||
private String key(ValueSetExpansionContainsComponent c) {
|
||||
return key(c.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.custommonkey.xmlunit.Diff;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.hamcrest.collection.IsEmptyCollection;
|
||||
|
@ -76,6 +78,24 @@ public class XmlParserDstu3Test {
|
|||
ourCtx.setNarrativeGenerator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* See #551
|
||||
*/
|
||||
@Test
|
||||
public void testXmlLargeAttribute() {
|
||||
String largeString = StringUtils.leftPad("", (int) FileUtils.ONE_MB, 'A');
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily(largeString);
|
||||
|
||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(p);
|
||||
|
||||
p = ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
||||
|
||||
assertEquals(largeString, p.getNameFirstRep().getFamily());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #544
|
||||
*/
|
||||
|
|
|
@ -98,7 +98,7 @@ public class GenericClientDstu3Test {
|
|||
byte[] body = IOUtils.toByteArray(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent());
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
|
||||
return body;
|
||||
|
@ -120,6 +120,26 @@ public class GenericClientDstu3Test {
|
|||
return capt;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevIncludeRecursive() throws ClientProtocolException, IOException {
|
||||
ArgumentCaptor<HttpUriRequest> capt = prepareClientForSearchResponse();
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
int idx = 0;
|
||||
|
||||
client.search()
|
||||
.forResource(EpisodeOfCare.class)
|
||||
.where(EpisodeOfCare.PATIENT.hasId("123"))
|
||||
.revInclude(Encounter.INCLUDE_EPISODEOFCARE)
|
||||
.revInclude(Observation.INCLUDE_ENCOUNTER.asRecursive())
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/EpisodeOfCare?patient=123&_revinclude=Encounter%3Aepisodeofcare&_revinclude%3Arecurse=Observation%3Aencounter", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchJsonByIdString() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -143,20 +163,21 @@ public class GenericClientDstu3Test {
|
|||
String patch = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":false } ]";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/123", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchJsonByIdType() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -180,20 +201,21 @@ public class GenericClientDstu3Test {
|
|||
String patch = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":false } ]";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId(new IdType("http://localhost/fhir/Patient/123/_history/234"))
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId(new IdType("http://localhost/fhir/Patient/123/_history/234"))
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/123", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchJsonByConditionalString() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -217,20 +239,21 @@ public class GenericClientDstu3Test {
|
|||
String patch = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":false } ]";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditionalByUrl("Patient?foo=bar")
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditionalByUrl("Patient?foo=bar")
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?foo=bar", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchJsonByConditionalParam() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -254,21 +277,22 @@ public class GenericClientDstu3Test {
|
|||
String patch = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":false } ]";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditional("Patient").where(Patient.NAME.matches().value("TEST"))
|
||||
.and(Patient.FAMILY.matches().value("TEST2"))
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditional("Patient").where(Patient.NAME.matches().value("TEST"))
|
||||
.and(Patient.FAMILY.matches().value("TEST2"))
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=TEST&family=TEST2", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchJsonByConditionalParamResourceType() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -292,21 +316,22 @@ public class GenericClientDstu3Test {
|
|||
String patch = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":false } ]";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditional(Patient.class).where(Patient.NAME.matches().value("TEST"))
|
||||
.and(Patient.FAMILY.matches().value("TEST2"))
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.conditional(Patient.class).where(Patient.NAME.matches().value("TEST"))
|
||||
.and(Patient.FAMILY.matches().value("TEST2"))
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=TEST&family=TEST2", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchXmlByIdString() throws Exception {
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
|
@ -330,31 +355,31 @@ public class GenericClientDstu3Test {
|
|||
String patch = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><diff xmlns:fhir=\"http://hl7.org/fhir\"><replace sel=\"fhir:Patient/fhir:active/@value\">false</replace></diff>";
|
||||
|
||||
MethodOutcome outcome = client
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody(patch)
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/123", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("PATCH", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
assertEquals(patch, extractBodyAsString(capt));
|
||||
assertEquals(Constants.CT_XML_PATCH, capt.getAllValues().get(idx).getFirstHeader("Content-Type").getValue().replaceAll(";.*", ""));
|
||||
idx++;
|
||||
|
||||
|
||||
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
|
||||
assertThat(oo.getText().getDivAsString(), containsString("OK!"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPatchInvalid() throws Exception {
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
try {
|
||||
client
|
||||
.patch()
|
||||
.withBody("AA")
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
.patch()
|
||||
.withBody("AA")
|
||||
.withId("Patient/123")
|
||||
.execute();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Unable to determine encoding of patch", e.getMessage());
|
||||
}
|
||||
|
@ -388,7 +413,7 @@ public class GenericClientDstu3Test {
|
|||
assertEquals("http://example.com/fhir/Device?_format=json", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("application/fhir+json;q=1.0, application/json+fhir;q=0.9", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_ACCEPT).getValue());
|
||||
idx++;
|
||||
|
||||
|
||||
//@formatter:off
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
client.search()
|
||||
|
@ -399,7 +424,7 @@ public class GenericClientDstu3Test {
|
|||
assertEquals("http://example.com/fhir/Device?_format=xml", UrlUtil.unescape(capt.getAllValues().get(idx).getURI().toString()));
|
||||
assertEquals("application/fhir+xml;q=1.0, application/xml+fhir;q=0.9", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_ACCEPT).getValue());
|
||||
idx++;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -480,9 +505,7 @@ public class GenericClientDstu3Test {
|
|||
assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, ourCtx.newXmlParser().parseResource(Binary.class, extractBodyAsString(capt)).getContent());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testClientFailures() throws Exception {
|
||||
|
@ -592,7 +615,7 @@ public class GenericClientDstu3Test {
|
|||
assertEquals(myAnswerCount, capt.getAllValues().size());
|
||||
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
assertEquals(Constants.CT_FHIR_XML_NEW, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
|
||||
|
||||
|
||||
assertEquals("http://foo.com/base/Patient/222/_history/3", capt.getAllValues().get(1).getURI().toASCIIString());
|
||||
}
|
||||
|
||||
|
@ -1027,7 +1050,7 @@ public class GenericClientDstu3Test {
|
|||
|
||||
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
|
||||
//@formatter:off
|
||||
client
|
||||
.search()
|
||||
|
@ -1053,22 +1076,22 @@ public class GenericClientDstu3Test {
|
|||
idx++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPutDoesntForceAllIdsJson() throws Exception {
|
||||
IParser p = ourCtx.newJsonParser();
|
||||
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("PATIENT1");
|
||||
patient.addName().setFamily("PATIENT1");
|
||||
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setId("BUNDLE1");
|
||||
bundle.addEntry().setResource(patient);
|
||||
|
||||
|
||||
final String encoded = p.encodeResourceToString(bundle);
|
||||
assertEquals("{\"resourceType\":\"Bundle\",\"id\":\"BUNDLE1\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"PATIENT1\",\"name\":[{\"family\":\"PATIENT1\"}]}}]}", encoded);
|
||||
|
||||
|
||||
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"));
|
||||
|
@ -1251,7 +1274,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=gt"+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=gt" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1261,7 +1284,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=gt"+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=gt" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1271,7 +1294,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=ge"+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=ge" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1281,7 +1304,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=lt"+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=lt" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1291,7 +1314,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=le"+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=le" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1301,7 +1324,7 @@ public class GenericClientDstu3Test {
|
|||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate="+dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?birthdate=" + dateString, capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -1639,7 +1662,7 @@ public class GenericClientDstu3Test {
|
|||
int idx = 0;
|
||||
|
||||
Collection<String> values = Arrays.asList("VAL1", "VAL2", "VAL3A,B");
|
||||
|
||||
|
||||
//@formatter:off
|
||||
client.search()
|
||||
.forResource("Patient")
|
||||
|
@ -1743,7 +1766,6 @@ public class GenericClientDstu3Test {
|
|||
assertEquals("Unable to determing encoding of request (body does not appear to be valid XML or JSON)", e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2012,7 +2034,7 @@ public class GenericClientDstu3Test {
|
|||
MyPatientWithExtensions patient = new MyPatientWithExtensions();
|
||||
patient.setId("123");
|
||||
patient.getText().setDivAsString("OK!");
|
||||
|
||||
|
||||
final String respString = p.encodeResourceToString(patient);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
@ -2028,7 +2050,7 @@ public class GenericClientDstu3Test {
|
|||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
MyPatientWithExtensions read = client.read().resource(MyPatientWithExtensions.class).withId(new IdType("1")).execute();
|
||||
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">OK!</div>", read.getText().getDivAsString());
|
||||
|
||||
|
||||
// Ensure that we haven't overridden the default type for the name
|
||||
assertFalse(MyPatientWithExtensions.class.isAssignableFrom(Patient.class));
|
||||
assertFalse(Patient.class.isAssignableFrom(MyPatientWithExtensions.class));
|
||||
|
@ -2037,7 +2059,7 @@ public class GenericClientDstu3Test {
|
|||
IParser parser = ourCtx.newXmlParser();
|
||||
String encoded = parser.encodeResourceToString(pt);
|
||||
pt = (Patient) parser.parseResource(encoded);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2045,13 +2067,12 @@ public class GenericClientDstu3Test {
|
|||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Bundle b = new Bundle();
|
||||
|
||||
|
||||
MyPatientWithExtensions patient = new MyPatientWithExtensions();
|
||||
patient.setId("123");
|
||||
patient.getText().setDivAsString("OK!");
|
||||
b.addEntry().setResource(patient);
|
||||
|
||||
|
||||
|
||||
final String respString = p.encodeResourceToString(b);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
@ -2066,7 +2087,7 @@ public class GenericClientDstu3Test {
|
|||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
Bundle bundle = client.search().forResource(MyPatientWithExtensions.class).returnBundle(Bundle.class).execute();
|
||||
|
||||
|
||||
assertEquals(1, bundle.getEntry().size());
|
||||
assertEquals(MyPatientWithExtensions.class, bundle.getEntry().get(0).getResource().getClass());
|
||||
}
|
||||
|
@ -2082,8 +2103,6 @@ public class GenericClientDstu3Test {
|
|||
assertEquals(expectedUserAgent(), capt.getAllValues().get(0).getHeaders("User-Agent")[0].getValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
@ -2093,5 +2112,5 @@ public class GenericClientDstu3Test {
|
|||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu3();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.either;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.oneOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
@ -65,7 +64,7 @@ public class SearchDefaultMethodDstu3Test {
|
|||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(ourLastMethod, either(equalTo("search01")).or(equalTo("search02")));
|
||||
assertThat(ourLastMethod, oneOf("search01", "search02", "search03"));
|
||||
assertEquals(null, ourLastParam1);
|
||||
assertEquals(null, ourLastParam2);
|
||||
assertEquals(null, ourLastAdditionalParams);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[*.java]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
@ -152,6 +152,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
throw new ConfigurationException(e);
|
||||
}
|
||||
|
||||
v.setShouldCheckForIdPresence(false);
|
||||
v.setBestPracticeWarningLevel(myBestPracticeWarningLevel);
|
||||
v.setAnyExtensionsAllowed(true);
|
||||
v.setRequireResourceId(false);
|
||||
|
|
|
@ -80,7 +80,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// used during the build process to keep the overall volume of messages down
|
||||
private boolean suppressLoincSnomedMessages;
|
||||
|
||||
public InstanceValidator(IWorkerContext theContext) throws Exception {
|
||||
private boolean shouldCheckForIdPresence = true;
|
||||
|
||||
public InstanceValidator(IWorkerContext theContext) throws Exception {
|
||||
super();
|
||||
this.context = theContext;
|
||||
source = Source.InstanceValidator;
|
||||
|
@ -117,6 +119,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
public void setShouldCheckForIdPresence(boolean theShouldCheckForIdPresence) {
|
||||
shouldCheckForIdPresence = theShouldCheckForIdPresence;
|
||||
}
|
||||
|
||||
private boolean check(String v1, String v2) {
|
||||
return v1 == null ? Utilities.noString(v1) : v1.equals(v2);
|
||||
}
|
||||
|
@ -1825,7 +1831,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (type.equals("Extension"))
|
||||
checkExtension(errors, ei.path, ei.element, ei.definition, profile, localStack);
|
||||
else if (type.equals("Resource"))
|
||||
validateContains(errors, ei.path, ei.definition, definition, ei.element, localStack, !isBundleEntry(ei.path) && !isParametersEntry(ei.path)); // if
|
||||
validateContains(errors, ei.path, ei.definition, definition, ei.element, localStack, !isBundleEntry(ei.path) && !isParametersEntry(ei.path) && shouldCheckForIdPresence); // if
|
||||
// (str.matches(".*([.,/])work\\1$"))
|
||||
else {
|
||||
StructureDefinition p = getProfileForType(type);
|
||||
|
|
|
@ -160,6 +160,11 @@ public class SearchHl7OrgDstu2Test {
|
|||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue