Merge branch 'master' into master
This commit is contained in:
commit
5811702a92
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.java]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>hapi-fhir-standalone-overlay-example</artifactId>
|
||||
<build>
|
||||
|
|
|
@ -70,7 +70,7 @@ public class ClientTransactionExamples {
|
|||
.setResource(patient)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setIfNoneExist("Patient?identifier=http://acme.org/mrns|12345")
|
||||
.setIfNoneExist("identifier=http://acme.org/mrns|12345")
|
||||
.setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
// Add the observation. This entry is a POST with no header
|
||||
|
|
|
@ -60,6 +60,11 @@ public class PagingPatientProvider implements IResourceProvider {
|
|||
// Typically this method just returns null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return new IBundleProvider() {
|
||||
|
||||
@Override
|
||||
public InstantDt getPublished() {
|
||||
public IPrimitiveType<Date> getPublished() {
|
||||
return resources.getPublished();
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -34,8 +37,10 @@ public interface IBundleProvider {
|
|||
* 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);
|
||||
|
@ -60,6 +65,21 @@ public interface IBundleProvider {
|
|||
/**
|
||||
* 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,
|
||||
|
|
|
@ -66,4 +66,9 @@ public class SimpleBundleProvider implements IBundleProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
@ -681,7 +681,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
|
|
@ -192,7 +192,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
preDelete(resourceToDelete);
|
||||
preDelete(resourceToDelete, entity);
|
||||
|
||||
// Notify interceptors
|
||||
if (theRequestDetails != null) {
|
||||
|
@ -722,7 +722,8 @@ 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) {
|
||||
@SuppressWarnings("unused")
|
||||
protected void preDelete(T theResourceToDelete, ResourceTable theEntityToDelete) {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
|
|
|
@ -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,20 +53,25 @@ 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());
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
|
@ -34,20 +32,23 @@ 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.jpa.util.DeleteConflict;
|
||||
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) {
|
||||
protected void markAffectedResources(SearchParameter theResource) {
|
||||
if (theResource != null) {
|
||||
String expression = theResource.getExpression();
|
||||
String resourceType = expression.substring(0, expression.indexOf('.'));
|
||||
|
@ -55,8 +56,9 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
int updatedCount = myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
ourLog.info("Marked {} resources for reindexing", updatedCount);
|
||||
}
|
||||
}
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called once per minute to perform any required re-indexing. During most passes this will
|
||||
|
@ -83,13 +85,6 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(SearchParameter theResourceToDelete) {
|
||||
super.preDelete(theResourceToDelete);
|
||||
markAffectedResources(theResourceToDelete);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
|
||||
super.postPersist(theEntity, theResource);
|
||||
|
@ -102,6 +97,12 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
markAffectedResources(theResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(SearchParameter theResourceToDelete, ResourceTable theEntityToDelete) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete);
|
||||
markAffectedResources(theResourceToDelete);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
|
||||
super.validateResourceForStorage(theResource, theEntityToSave);
|
||||
|
@ -115,9 +116,18 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
throw new UnprocessableEntityException("SearchParameter.expression is missing");
|
||||
}
|
||||
|
||||
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 : expressionSplit) {
|
||||
nextPath = nextPath.trim();
|
||||
|
||||
int dotIdx = nextPath.indexOf('.');
|
||||
if (dotIdx == -1) {
|
||||
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -521,6 +522,15 @@ 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();
|
||||
|
@ -118,7 +143,7 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
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) {
|
||||
|
@ -134,22 +159,6 @@ 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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
@ -9,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;
|
||||
|
@ -19,7 +20,6 @@ import org.junit.Test;
|
|||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
|
@ -29,6 +29,7 @@ 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");
|
||||
|
@ -43,9 +44,27 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
}
|
||||
}
|
||||
|
||||
@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");
|
||||
|
@ -63,6 +82,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
@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");
|
||||
|
@ -79,6 +99,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
@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");
|
||||
|
@ -97,6 +118,7 @@ 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");
|
||||
|
@ -112,10 +134,65 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
|
||||
}
|
||||
|
||||
@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");
|
||||
|
@ -169,6 +246,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
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");
|
||||
|
|
|
@ -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;
|
||||
|
@ -53,6 +54,9 @@ 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());
|
||||
|
@ -116,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();
|
||||
|
@ -144,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();
|
||||
|
@ -162,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
|
||||
|
@ -207,170 +236,6 @@ 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"));
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@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"));
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||
|
||||
@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 testExpandInvalid() {
|
||||
createExternalCsAndLocalVs();
|
||||
|
@ -390,43 +255,110 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
|
||||
@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");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
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");
|
||||
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
||||
myValueSetDao.create(valueSet, mySrd);
|
||||
|
||||
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"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -463,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();
|
||||
|
@ -493,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();
|
||||
|
@ -520,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);
|
||||
|
@ -560,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
|
||||
*/
|
||||
|
@ -594,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();
|
||||
|
@ -636,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();
|
||||
|
@ -824,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();
|
||||
|
@ -848,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();
|
||||
|
@ -941,6 +1027,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchCodeInLocalCodesystem() {
|
||||
createLocalCsAndVs();
|
||||
|
@ -963,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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -70,6 +72,55 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@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,6 +148,7 @@ 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");
|
||||
|
@ -107,6 +159,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
|
||||
// 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");
|
||||
|
@ -149,6 +202,7 @@ 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");
|
||||
|
@ -159,6 +213,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
|
|||
|
||||
// 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");
|
||||
|
@ -203,6 +258,7 @@ 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");
|
||||
|
@ -254,6 +310,7 @@ 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");
|
||||
|
@ -274,6 +331,7 @@ 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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -177,8 +177,14 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<!--
|
||||
This project is built to 1.8 since our public
|
||||
server runs on a 1.8 JDK. If you are using this
|
||||
project as a basis for your own work, you could
|
||||
probably safely reduce this if needed
|
||||
-->
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings
|
||||
|
|
|
@ -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:
|
||||
|
||||
* 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.
|
||||
* 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.
|
||||
* 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.
|
||||
|
||||
*/
|
||||
* 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,36 +72,36 @@ 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);
|
||||
n.setSystem(system);
|
||||
n.setCode(code);
|
||||
if (isAbstract)
|
||||
n.setAbstract(true);
|
||||
if (inactive)
|
||||
|
@ -109,29 +109,30 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
|
||||
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);
|
||||
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());
|
||||
}
|
||||
for (ConceptReferenceComponent c : exc.getConcept()) {
|
||||
excludeCode(exc.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
if (exc.getFilter().size() > 0)
|
||||
throw new NotImplementedException("not done yet");
|
||||
}
|
||||
if (exc.getFilter().size() > 0)
|
||||
throw new NotImplementedException("not done yet");
|
||||
}
|
||||
|
||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(c.getSystem(), c.getCode());
|
||||
}
|
||||
}
|
||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(c.getSystem(), c.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
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 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
|
||||
@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>();
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
mode. This allows users to create search parameters which contain
|
||||
custom paths, or even override and disable existing search
|
||||
parameters.
|
||||
</action>
|
||||
<action type="fix">
|
||||
CLI example uploader couldn't find STU3 examples after CI server
|
||||
was moved to build.fhir.org
|
||||
|
@ -138,6 +139,24 @@
|
|||
JPA server did not return an OperationOutcome in the response for
|
||||
a normal delete operation.
|
||||
</action>
|
||||
<action type="fix">
|
||||
Fix an issue in JPA server where _history results were kept in memory instead
|
||||
of being spooled to the database as they should be. Note that as a part of this fix
|
||||
a new method was added to
|
||||
<![CDATA[<code>IBundleProvider</code> called <code>getUuid()</code>]]>. This
|
||||
method may return <![CDATA[<code>null</code>]]> in any current cases.
|
||||
</action>
|
||||
<action type="fix">
|
||||
Expanding a ValueSet in JPA server did not correctly apply
|
||||
<![CDATA[<code>?filter=</code>]]> parameter when the ValueSet
|
||||
being expanded had codes included explicitly (i.e. not by
|
||||
is-a relationship). Thanks to David Hay for reporting!
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA validator incorrectly returned an HTTP 400 instead of an HTTP 422 when
|
||||
the resource ID was not present and required, or vice versa. Thanks to
|
||||
Brian Postlethwaite for reporting!
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.2" date="2016-12-20">
|
||||
<action type="add">
|
||||
|
|
|
@ -81,6 +81,23 @@
|
|||
</answer>
|
||||
</faq>
|
||||
</part>
|
||||
<part id="Using HAPI">
|
||||
<title>Using HAPI</title>
|
||||
<faq id="jdk_version">
|
||||
<question>
|
||||
What JDK version does HAPI support?
|
||||
</question>
|
||||
<answer>
|
||||
<p>
|
||||
HAPI supports JDK 1.6 for the entire library, except for the CLI tool which is 1.8.
|
||||
</p>
|
||||
<p>
|
||||
Note that the HAPI library itself also requires a 1.8 JDK to build, since the unit tests
|
||||
have JDK 1.8 dependencies.
|
||||
</p>
|
||||
</answer>
|
||||
</faq>
|
||||
</part>
|
||||
<part id="JPA Server">
|
||||
<title>JPA Server</title>
|
||||
<faq id="access_underlying_derby_database">
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<request>
|
||||
<method value="POST"/>
|
||||
<url value="Patient"/>
|
||||
<ifNoneExist value="Patient?identifier=http://acme.org/mrns|12345"/>
|
||||
<ifNoneExist value="identifier=http://acme.org/mrns|12345"/>
|
||||
</request>
|
||||
</entry>
|
||||
<entry>
|
||||
|
|
Loading…
Reference in New Issue