Add support for $validate-code in JPA server
This commit is contained in:
parent
257908cf0a
commit
ddc66d3ed0
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.model.primitive;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import net.sourceforge.cobertura.CoverageIgnore;
|
||||
|
||||
|
|
|
@ -59,16 +59,16 @@ public @interface OperationParam {
|
|||
Class<? extends IBase> type() default IBase.class;
|
||||
|
||||
/**
|
||||
* The minimum number of repetitions allowed for this child
|
||||
* The minimum number of repetitions allowed for this child (default is 0)
|
||||
*/
|
||||
int min() default 0;
|
||||
|
||||
/**
|
||||
* The maximum number of repetitions allowed for this child. Should be
|
||||
* set to {@link #MAX_UNLIMITED} if there is no limit to the number of
|
||||
* repetitions.
|
||||
* repetitions (default is 1)
|
||||
*/
|
||||
int max() default MAX_UNLIMITED;
|
||||
int max() default 1;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.rest.client.interceptor;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
|
|
@ -174,6 +174,10 @@
|
|||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Hibernate -->
|
||||
<dependency>
|
||||
|
|
|
@ -19,8 +19,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
|
@ -115,7 +115,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public abstract class BaseHapiFhirDao implements IDao {
|
||||
public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
||||
|
||||
public static final String NS_JPA_PROFILE = "https://github.com/jamesagnew/hapi-fhir/ns/jpa/profile";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirDao.class);
|
||||
|
@ -344,7 +344,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends IBaseResource> IFhirResourceDao<T> getDao(Class<T> theType) {
|
||||
protected <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
|
||||
if (myResourceTypeToDao == null) {
|
||||
myResourceTypeToDao = new HashMap<Class<? extends IBaseResource>, IFhirResourceDao<?>>();
|
||||
for (IFhirResourceDao<?> next : myResourceDaos) {
|
||||
|
@ -358,7 +358,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
|
||||
}
|
||||
|
||||
return (IFhirResourceDao<T>) myResourceTypeToDao.get(theType);
|
||||
return (IFhirResourceDao<R>) myResourceTypeToDao.get(theType);
|
||||
}
|
||||
|
||||
protected TagDefinition getTag(TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||
|
@ -644,12 +644,12 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
|
||||
}
|
||||
|
||||
protected <T extends IResource> Set<Long> processMatchUrl(String theMatchUrl, Class<T> theResourceType) {
|
||||
protected <R extends IResource> Set<Long> processMatchUrl(String theMatchUrl, Class<R> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
||||
|
||||
IFhirResourceDao<T> dao = getDao(theResourceType);
|
||||
IFhirResourceDao<R> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
|
@ -899,6 +899,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
case DSTU1:
|
||||
mySearchParamExtractor = new SearchParamExtractorDstu1(theContext);
|
||||
break;
|
||||
case DSTU2_HL7ORG:
|
||||
case DEV:
|
||||
throw new IllegalStateException("Don't know how to handle version: " + myContext.getVersion().getVersion());
|
||||
}
|
||||
|
@ -917,7 +918,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
return toResource(type.getImplementingClass(), theEntity);
|
||||
}
|
||||
|
||||
protected <T extends IBaseResource> T toResource(Class<T> theResourceType, BaseHasResource theEntity) {
|
||||
protected <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity) {
|
||||
String resourceText = null;
|
||||
switch (theEntity.getEncoding()) {
|
||||
case JSON:
|
||||
|
@ -933,7 +934,7 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
}
|
||||
|
||||
IParser parser = theEntity.getEncoding().newParser(getContext(theEntity.getFhirVersion()));
|
||||
T retVal;
|
||||
R retVal;
|
||||
try {
|
||||
retVal = parser.parseResource(theResourceType, resourceText);
|
||||
} catch (Exception e) {
|
||||
|
@ -955,9 +956,9 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
IResource res = (IResource) retVal;
|
||||
res.setId(theEntity.getIdDt());
|
||||
|
||||
res.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, theEntity.getVersion());
|
||||
res.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, theEntity.getPublished());
|
||||
res.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, theEntity.getUpdated());
|
||||
ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion()));
|
||||
ResourceMetadataKeyEnum.PUBLISHED.put(res, theEntity.getPublished());
|
||||
ResourceMetadataKeyEnum.UPDATED.put(res, theEntity.getUpdated());
|
||||
|
||||
if (theEntity.getTitle() != null) {
|
||||
ResourceMetadataKeyEnum.TITLE.put(res, theEntity.getTitle());
|
||||
|
@ -1038,9 +1039,10 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
|
||||
|
||||
validateResourceForStorage(theResource);
|
||||
validateResourceForStorage((T) theResource);
|
||||
|
||||
if (entity.getPublished() == null) {
|
||||
entity.setPublished(new Date());
|
||||
|
@ -1216,12 +1218,15 @@ public abstract class BaseHapiFhirDao implements IDao {
|
|||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override to provide specific behaviour
|
||||
* This method is invoked immediately before storing a new resource, or an
|
||||
* update to an existing resource to allow the DAO to ensure that it is valid
|
||||
* for persistence. By default, no validation is performed, but subclasses
|
||||
* may override to provide specific behaviour.
|
||||
*
|
||||
* @param theResource
|
||||
* The resource that is about to be persisted
|
||||
*/
|
||||
protected void validateResourceForStorage(IResource theResource) {
|
||||
protected void validateResourceForStorage(T theResource) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ import ca.uhn.fhir.util.FhirTerser;
|
|||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseHapiFhirDao implements IFhirResourceDao<T> {
|
||||
public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseHapiFhirDao<T> implements IFhirResourceDao<T> {
|
||||
|
||||
static final String OO_SEVERITY_WARN = "warning";
|
||||
static final String OO_SEVERITY_INFO = "information";
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
@ -7,7 +27,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
|
||||
|
@ -39,7 +58,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void validateResourceForStorage(IResource theResource) {
|
||||
protected void validateResourceForStorage(QuestionnaireResponse theResource) {
|
||||
super.validateResourceForStorage(theResource);
|
||||
if (!myValidateResponses) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.codec.binary.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeInclude;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeIncludeConcept;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ExpansionContains;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>implements IFhirResourceDaoValueSet<ValueSet> {
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, StringDt theFilter) {
|
||||
ValueSet retVal = new ValueSet();
|
||||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
|
||||
BaseHasResource sourceEntity = readEntity(theId);
|
||||
if (sourceEntity == null) {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
ValueSet source = (ValueSet) toResource(sourceEntity);
|
||||
|
||||
/*
|
||||
* Add composed concepts
|
||||
*/
|
||||
|
||||
for (ComposeInclude nextInclude : source.getCompose().getInclude()) {
|
||||
for (ComposeIncludeConcept next : nextInclude.getConcept()) {
|
||||
if (theFilter == null || theFilter.isEmpty()) {
|
||||
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
|
||||
} else {
|
||||
String filter = theFilter.getValue().toLowerCase();
|
||||
if (next.getDisplay().toLowerCase().contains(filter) || next.getCode().toLowerCase().contains(filter)) {
|
||||
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add defined concepts
|
||||
*/
|
||||
|
||||
for (CodeSystemConcept next : source.getCodeSystem().getConcept()) {
|
||||
addCompose(theFilter, retVal, source, next);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
}
|
||||
|
||||
private void addCompose(StringDt theFilter, ValueSet theValueSetToPopulate, ValueSet theSourceValueSet, CodeSystemConcept theConcept) {
|
||||
if (theFilter == null || theFilter.isEmpty()) {
|
||||
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
|
||||
} else {
|
||||
String filter = theFilter.getValue().toLowerCase();
|
||||
if (theConcept.getDisplay().toLowerCase().contains(filter) || theConcept.getCode().toLowerCase().contains(filter)) {
|
||||
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
|
||||
}
|
||||
}
|
||||
for (CodeSystemConcept nextChild : theConcept.getConcept()) {
|
||||
addCompose(theFilter, theValueSetToPopulate, theSourceValueSet, nextChild);
|
||||
}
|
||||
}
|
||||
|
||||
private void addCompose(ValueSet retVal, String theSystem, String theCode, String theDisplay) {
|
||||
if (isBlank(theCode)) {
|
||||
return;
|
||||
}
|
||||
ExpansionContains contains = retVal.getExpansion().addContains();
|
||||
contains.setSystem(theSystem);
|
||||
contains.setCode(theCode);
|
||||
contains.setDisplay(theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(UriDt theValueSetIdentifier, IIdType theId, CodeDt theCode, UriDt theSystem, StringDt theDisplay,
|
||||
CodingDt theCoding, CodeableConceptDt theCodeableConcept) {
|
||||
List<IIdType> valueSetIds;
|
||||
|
||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
||||
boolean haveCoding = theCoding != null && theCoding.isEmpty() == false;
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
|
||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!(haveCodeableConcept ^ haveCoding ^ haveCode)) {
|
||||
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
boolean haveIdentifierParam = theValueSetIdentifier != null && theValueSetIdentifier.isEmpty() == false;
|
||||
if (theId != null) {
|
||||
valueSetIds = Collections.singletonList((IIdType) theId);
|
||||
} else if (haveIdentifierParam) {
|
||||
Set<Long> ids = searchForIds(ValueSet.SP_IDENTIFIER, new TokenParam(null, theValueSetIdentifier.getValue()));
|
||||
valueSetIds = new ArrayList<IIdType>();
|
||||
for (Long next : ids) {
|
||||
valueSetIds.add(new IdDt("ValueSet", next));
|
||||
}
|
||||
} else {
|
||||
if (theCode == null || theCode.isEmpty()) {
|
||||
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
||||
}
|
||||
Set<Long> ids = searchForIds(ValueSet.SP_CODE, new TokenParam(toStringOrNull(theSystem), theCode.getValue()));
|
||||
valueSetIds = new ArrayList<IIdType>();
|
||||
for (Long next : ids) {
|
||||
valueSetIds.add(new IdDt("ValueSet", next));
|
||||
}
|
||||
}
|
||||
|
||||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null);
|
||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
||||
if (!theDisplay.getValue().equals(result.getDisplay())) {
|
||||
return new ValidateCodeResult(false, "Display for code does not match", result.getDisplay());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return new ValidateCodeResult(false, "Code not found", null);
|
||||
}
|
||||
|
||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||
}
|
||||
|
||||
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ExpansionContains> contains, String theSystem, String theCode, CodingDt theCoding,
|
||||
CodeableConceptDt theCodeableConcept) {
|
||||
for (ExpansionContains nextCode : contains) {
|
||||
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
String system = nextCode.getSystem();
|
||||
String code = nextCode.getCode();
|
||||
|
||||
if (isNotBlank(theCode)) {
|
||||
if (theCode.equals(code) && (isBlank(theSystem) || theSystem.equals(system))) {
|
||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
||||
}
|
||||
} else if (theCoding != null) {
|
||||
if (StringUtils.equals(system, theCoding.getSystem()) && StringUtils.equals(code, theCoding.getCode())) {
|
||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
||||
}
|
||||
} else {
|
||||
for (CodingDt next : theCodeableConcept.getCoding()) {
|
||||
if (StringUtils.equals(system, next.getSystem()) && StringUtils.equals(code, next.getCode())) {
|
||||
return new ValidateCodeResult(true, "Validation succeeded", nextCode.getDisplay());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
||||
public interface IFhirResourceDaoValueSet<T extends IBaseResource> extends IFhirResourceDao<T> {
|
||||
|
||||
ValueSet expand(IIdType theId, StringDt theFilter);
|
||||
|
||||
ValidateCodeResult validateCode(UriDt theValueSetIdentifier, IIdType theId, CodeDt theCode, UriDt theSystem, StringDt theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept);
|
||||
|
||||
public class ValidateCodeResult {
|
||||
private String myDisplay;
|
||||
private String myMessage;
|
||||
private boolean myResult;
|
||||
|
||||
public ValidateCodeResult(boolean theResult, String theMessage, String theDisplay) {
|
||||
super();
|
||||
myResult = theResult;
|
||||
myMessage = theMessage;
|
||||
myDisplay = theDisplay;
|
||||
}
|
||||
|
||||
public String getDisplay() {
|
||||
return myDisplay;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
public boolean isResult() {
|
||||
return myResult;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -63,6 +63,7 @@ import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient.Communication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.RestfulSecurityServiceEnum;
|
||||
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
|
@ -405,6 +406,12 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
public List<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<BaseResourceIndexedSearchParam> retVal = new ArrayList<BaseResourceIndexedSearchParam>();
|
||||
|
||||
String useSystem = null;
|
||||
if (theResource instanceof ValueSet) {
|
||||
ValueSet vs = (ValueSet) theResource;
|
||||
useSystem = vs.getCodeSystem().getSystem();
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
||||
|
@ -466,7 +473,11 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
systems.add(null);
|
||||
if ("ValueSet.codeSystem.concept.code".equals(nextPath)) {
|
||||
systems.add(useSystem);
|
||||
} else {
|
||||
systems.add(null);
|
||||
}
|
||||
codes.add(nextValue.getValueAsString());
|
||||
} else if (nextObject instanceof CodingDt) {
|
||||
CodingDt nextValue = (CodingDt) nextObject;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
|
||||
|
||||
public class BaseJpaResourceProviderQuestionnaireResponseDstu2 extends JpaResourceProviderDstu2<QuestionnaireResponse> {
|
||||
|
|
|
@ -1,116 +1,76 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeInclude;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeIncludeConcept;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
||||
public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDstu2<ValueSet> {
|
||||
|
||||
//@formatter:off
|
||||
@Operation(name = "$expand", idempotent = true)
|
||||
public ValueSet everything(HttpServletRequest theServletRequest, @IdParam IdDt theId, @OperationParam(name = "filter") StringDt theFilter) {
|
||||
public ValueSet everything(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam IdDt theId,
|
||||
@OperationParam(name = "filter") StringDt theFilter) {
|
||||
//@formatter:on
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
ValueSet retVal = new ValueSet();
|
||||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
|
||||
ValueSet source = read(theServletRequest, theId);
|
||||
|
||||
Map<String, ComposeInclude> systemToCompose = new HashMap<String, ComposeInclude>();
|
||||
|
||||
/*
|
||||
* Add composed concepts
|
||||
*/
|
||||
|
||||
for (ComposeInclude nextInclude : source.getCompose().getInclude()) {
|
||||
for (ComposeIncludeConcept next : nextInclude.getConcept()) {
|
||||
ComposeInclude include = null;
|
||||
if (theFilter == null || theFilter.isEmpty()) {
|
||||
if (include == null) {
|
||||
include = getOrAddComposeInclude(retVal, systemToCompose, nextInclude.getSystem());
|
||||
}
|
||||
include.addConcept(next);
|
||||
} else {
|
||||
String filter = theFilter.getValue().toLowerCase();
|
||||
if (next.getDisplay().toLowerCase().contains(filter) || next.getCode().toLowerCase().contains(filter)) {
|
||||
if (include == null) {
|
||||
include = getOrAddComposeInclude(retVal, systemToCompose, nextInclude.getSystem());
|
||||
}
|
||||
include.addConcept(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add defined concepts
|
||||
*/
|
||||
|
||||
ComposeInclude include = null;
|
||||
for (CodeSystemConcept next : source.getCodeSystem().getConcept()) {
|
||||
if (theFilter == null || theFilter.isEmpty()) {
|
||||
if (include == null) {
|
||||
include = getOrAddComposeInclude(retVal, systemToCompose, source.getCodeSystem().getSystem());
|
||||
}
|
||||
include.addConcept(new ComposeIncludeConcept().setCode(next.getCode()).setDisplay(next.getDisplay()));
|
||||
} else {
|
||||
String filter = theFilter.getValue().toLowerCase();
|
||||
if (next.getDisplay().toLowerCase().contains(filter) || next.getCode().toLowerCase().contains(filter)) {
|
||||
if (include == null) {
|
||||
include = getOrAddComposeInclude(retVal, systemToCompose, source.getCodeSystem().getSystem());
|
||||
}
|
||||
include.addConcept(new ComposeIncludeConcept().setCode(next.getCode()).setDisplay(next.getDisplay()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
|
||||
return dao.expand(theId, theFilter);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private ComposeInclude getOrAddComposeInclude(ValueSet retVal, Map<String, ComposeInclude> systemToCompose, String system) {
|
||||
ComposeInclude include;
|
||||
include = systemToCompose.get(system);
|
||||
if (include == null) {
|
||||
include = retVal.getCompose().addInclude();
|
||||
include.setSystem(system);
|
||||
systemToCompose.put(system, include);
|
||||
}
|
||||
return include;
|
||||
}
|
||||
//@formatter:off
|
||||
@Operation(name = "$validate-code", idempotent = true, returnParameters= {
|
||||
@OperationParam(name="result", type=BooleanDt.class, min=1),
|
||||
@OperationParam(name="message", type=StringDt.class),
|
||||
@OperationParam(name="display", type=StringDt.class)
|
||||
})
|
||||
public Parameters everything(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam IdDt theId,
|
||||
@OperationParam(name="identifier") UriDt theValueSetIdentifier,
|
||||
@OperationParam(name="code") CodeDt theCode,
|
||||
@OperationParam(name="system") UriDt theSystem,
|
||||
@OperationParam(name="display") StringDt theDisplay,
|
||||
@OperationParam(name="coding") CodingDt theCoding,
|
||||
@OperationParam(name="codeableConcept") CodeableConceptDt theCodeableConcept
|
||||
) {
|
||||
//@formatter:on
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
|
||||
ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept);
|
||||
Parameters retVal = new Parameters();
|
||||
retVal.addParameter().setName("result").setValue(new BooleanDt(result.isResult()));
|
||||
if (isNotBlank(result.getMessage())) {
|
||||
retVal.addParameter().setName("message").setValue(new StringDt(result.getMessage()));
|
||||
}
|
||||
if (isNotBlank(result.getDisplay())) {
|
||||
retVal.addParameter().setName("display").setValue(new StringDt(result.getDisplay()));
|
||||
}
|
||||
return retVal;
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||
import ca.uhn.fhir.jpa.provider.ResourceProviderDstu2Test;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration({ "/hapi-fhir-server-resourceproviders-dstu2.xml", "/fhir-jpabase-spring-test-config.xml" })
|
||||
public class FhirResourceDaoValueSetDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoValueSetDstu2Test.class);
|
||||
|
||||
private static IIdType vsid;
|
||||
|
||||
@Autowired
|
||||
private FhirContext myCtx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mySystemDaoDstu2")
|
||||
private IFhirSystemDao<Bundle> mySystemDao;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("myValueSetDaoDstu2")
|
||||
private IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
|
||||
|
||||
@Before
|
||||
@Transactional
|
||||
public void before01() {
|
||||
if (vsid == null) {
|
||||
FhirSystemDaoDstu2Test.doDeleteEverything(mySystemDao);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
@Transactional
|
||||
public void before02() {
|
||||
if (vsid == null) {
|
||||
ValueSet upload = myCtx.newXmlParser().parseResource(ValueSet.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/extensional-case-2.xml")));
|
||||
upload.setId("");
|
||||
vsid = myValueSetDao.create(upload).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemBad() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
IdDt id = null;
|
||||
CodeDt code = new CodeDt("8450-9-XXX");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertFalse(result.isResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByCodeAndSystemGood() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
IdDt id = null;
|
||||
CodeDt code = new CodeDt("8450-9");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByIdentifierAndCodeAndSystem() {
|
||||
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||
IdDt id = null;
|
||||
CodeDt code = new CodeDt("11378-7");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByIdentifierAndCodeAndSystemAndBadDisplay() {
|
||||
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||
IdDt id = null;
|
||||
CodeDt code = new CodeDt("11378-7");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = new StringDt("Systolic blood pressure at First encounterXXXX");
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertFalse(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByIdentifierAndCodeAndSystemAndGoodDisplay() {
|
||||
UriDt valueSetIdentifier = new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
|
||||
IdDt id = null;
|
||||
CodeDt code = new CodeDt("11378-7");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByResourceIdAndCodeableConcept() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
IIdType id = vsid;
|
||||
CodeDt code = null;
|
||||
UriDt system = null;
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeOperationByResourceIdAndCodeAndSystem() {
|
||||
UriDt valueSetIdentifier = null;
|
||||
IIdType id = vsid;
|
||||
CodeDt code = new CodeDt("11378-7");
|
||||
UriDt system = new UriDt("http://loinc.org");
|
||||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = null;
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValueSetExpandOperation() throws IOException {
|
||||
String resp;
|
||||
|
||||
ValueSet expanded = myValueSetDao.expand(vsid, null);
|
||||
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
// @formatter:off
|
||||
assertThat(resp,
|
||||
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
|
||||
"<expansion>",
|
||||
"<contains>",
|
||||
"<system value=\"http://loinc.org\"/>",
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>",
|
||||
"</contains>",
|
||||
"<contains>",
|
||||
"<system value=\"http://loinc.org\"/>",
|
||||
"<code value=\"8450-9\"/>",
|
||||
"<display value=\"Systolic blood pressure--expiration\"/>",
|
||||
"</contains>",
|
||||
"</expansion>"
|
||||
));
|
||||
//@formatter:on
|
||||
|
||||
/*
|
||||
* Filter with display name
|
||||
*/
|
||||
|
||||
expanded = myValueSetDao.expand(vsid, new StringDt("systolic"));
|
||||
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
assertThat(resp, stringContainsInOrder(
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
//@formatter:on
|
||||
|
||||
/*
|
||||
* Filter with code
|
||||
*/
|
||||
|
||||
expanded = myValueSetDao.expand(vsid, new StringDt("11378"));
|
||||
resp = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
assertThat(resp, stringContainsInOrder(
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>"));
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
}
|
|
@ -428,8 +428,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
|
||||
@Test
|
||||
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
|
||||
String methodName = "testCreateQuestionnaireResponseWithValidation";
|
||||
|
||||
ValueSet options = new ValueSet();
|
||||
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
|
||||
IIdType optId = ourClient.create().resource(options).execute().getId();
|
||||
|
@ -1508,21 +1506,21 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
|
|||
ourLog.info(resp);
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
// @formatter:off
|
||||
assertThat(
|
||||
resp,
|
||||
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
|
||||
"<compose>",
|
||||
"<include>",
|
||||
assertThat(resp,
|
||||
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
|
||||
"<expansion>",
|
||||
"<contains>",
|
||||
"<system value=\"http://loinc.org\"/>",
|
||||
"<concept>",
|
||||
"<code value=\"11378-7\"/>",
|
||||
"<display value=\"Systolic blood pressure at First encounter\"/>",
|
||||
"</concept>",
|
||||
"<concept>",
|
||||
"</contains>",
|
||||
"<contains>",
|
||||
"<system value=\"http://loinc.org\"/>",
|
||||
"<code value=\"8450-9\"/>",
|
||||
"<display value=\"Systolic blood pressure--expiration\"/>",
|
||||
"</concept>"
|
||||
));
|
||||
"</contains>",
|
||||
"</expansion>"
|
||||
));
|
||||
//@formatter:on
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
#foreach ( $res in $resources )
|
||||
<bean id="my${res.name}Dao${versionCapitalized}"
|
||||
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'QuestionnaireResponse' ))
|
||||
## Some resource types have customized DAOs for resource specific functionality
|
||||
#if ( ${versionCapitalized} == 'Dstu2' && ( ${res.name} == 'Bundle' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'ValueSet'))
|
||||
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${res.name}${versionCapitalized}">
|
||||
#else
|
||||
class="ca.uhn.fhir.jpa.dao.FhirResourceDao${versionCapitalized}">
|
||||
|
|
5
pom.xml
5
pom.xml
|
@ -336,6 +336,11 @@
|
|||
<artifactId>spring-orm</artifactId>
|
||||
<version>${spring_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
|
|
|
@ -93,6 +93,9 @@
|
|||
a resourceType element) fail to parse with a confusing NullPointerException.
|
||||
Thanks to GitHub user @hugosoares for reporting!
|
||||
</action>
|
||||
<action type="add">
|
||||
JPA server now implements the $validate-code operation
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.1" date="2015-07-13">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue