Fix teerm sevice indexing
This commit is contained in:
parent
fae4344c36
commit
e9cb518012
|
@ -101,6 +101,7 @@ public class BaseDstu3Config extends BaseConfig {
|
||||||
@Bean(name = "mySystemProviderDstu3")
|
@Bean(name = "mySystemProviderDstu3")
|
||||||
public ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3 systemProviderDstu3() {
|
public ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3 systemProviderDstu3() {
|
||||||
ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3 retVal = new ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3();
|
ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3 retVal = new ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3();
|
||||||
|
retVal.setContext(defaultFhirContext());
|
||||||
retVal.setDao(systemDaoDstu3());
|
retVal.setDao(systemDaoDstu3());
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1174,7 +1174,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
||||||
coordsParams = extractSearchParamCoords(theEntity, theResource);
|
coordsParams = extractSearchParamCoords(theEntity, theResource);
|
||||||
|
|
||||||
// ourLog.info("Indexing resource: {}", entity.getId());
|
// ourLog.info("Indexing resource: {}", entity.getId());
|
||||||
ourLog.info("Storing date indexes: {}", dateParams);
|
ourLog.trace("Storing date indexes: {}", dateParams);
|
||||||
|
|
||||||
tokenParams = new HashSet<ResourceIndexedSearchParamToken>();
|
tokenParams = new HashSet<ResourceIndexedSearchParamToken>();
|
||||||
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theEntity, theResource)) {
|
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theEntity, theResource)) {
|
||||||
|
|
|
@ -37,8 +37,6 @@ import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
@ -50,7 +48,6 @@ import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ITermConceptDao;
|
import ca.uhn.fhir.jpa.dao.data.ITermConceptDao;
|
||||||
import ca.uhn.fhir.jpa.entity.ForcedId;
|
import ca.uhn.fhir.jpa.entity.ForcedId;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
|
||||||
import ca.uhn.fhir.jpa.util.ReindexFailureException;
|
import ca.uhn.fhir.jpa.util.ReindexFailureException;
|
||||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
|
@ -89,7 +86,6 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
|
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
|
||||||
int retVal = doPerformReindexingPassForResources(theCount, txTemplate);
|
int retVal = doPerformReindexingPassForResources(theCount, txTemplate);
|
||||||
retVal += doPerformReindexingPassForConcepts(txTemplate);
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,37 +148,6 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private int doPerformReindexingPassForConcepts(TransactionTemplate txTemplate) {
|
|
||||||
return txTemplate.execute(new TransactionCallback<Integer>() {
|
|
||||||
@Override
|
|
||||||
public Integer doInTransaction(TransactionStatus theStatus) {
|
|
||||||
|
|
||||||
int maxResult = 10000;
|
|
||||||
Page<TermConcept> resources = myTermConceptDao.findResourcesRequiringReindexing(new PageRequest(0, maxResult));
|
|
||||||
if (resources.hasContent() == false) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ourLog.info("Indexing {} / {} concepts", resources.getContent().size(), resources.getTotalElements());
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (TermConcept resourceTable : resources) {
|
|
||||||
resourceTable.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
|
||||||
myTermConceptDao.save(resourceTable);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
long delay = System.currentTimeMillis() - start;
|
|
||||||
long avg = (delay / resources.getContent().size());
|
|
||||||
ourLog.info("Indexed {} / {} concepts in {}ms - Avg {}ms / resource", new Object[] { count, resources.getContent().size(), delay, avg });
|
|
||||||
|
|
||||||
return resources.getContent().size();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagList getAllTags(RequestDetails theRequestDetails) {
|
public TagList getAllTags(RequestDetails theRequestDetails) {
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueSet expand(IIdType theId, String theFilter) {
|
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||||
ValueSet source = loadValueSetForExpansion(theId);
|
ValueSet source = loadValueSetForExpansion(theId);
|
||||||
return expand(source, theFilter);
|
return expand(source, theFilter);
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept) {
|
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
List<IIdType> valueSetIds;
|
List<IIdType> valueSetIds;
|
||||||
|
|
||||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
||||||
|
@ -212,7 +212,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IIdType nextId : valueSetIds) {
|
for (IIdType nextId : valueSetIds) {
|
||||||
ValueSet expansion = expand(nextId, null);
|
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
@ -314,7 +314,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
||||||
|
|
||||||
List<IIdType> valueSetIds = findCodeSystemIdsContainingSystemAndCode(code, system);
|
List<IIdType> valueSetIds = findCodeSystemIdsContainingSystemAndCode(code, system);
|
||||||
for (IIdType nextId : valueSetIds) {
|
for (IIdType nextId : valueSetIds) {
|
||||||
ValueSet expansion = expand(nextId, null);
|
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||||
LookupCodeResult result = lookup(contains, system, code);
|
LookupCodeResult result = lookup(contains, system, code);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
|
|
@ -24,9 +24,11 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
|
|
||||||
public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> extends IFhirResourceDao<T> {
|
public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> extends IFhirResourceDao<T> {
|
||||||
|
|
||||||
T expand(IIdType theId, String theFilter);
|
T expand(IIdType theId, String theFilter, RequestDetails theRequestDetails);
|
||||||
|
|
||||||
T expand(T theSource, String theFilter);
|
T expand(T theSource, String theFilter);
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> exten
|
||||||
|
|
||||||
void purgeCaches();
|
void purgeCaches();
|
||||||
|
|
||||||
ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept);
|
ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept, RequestDetails theRequestDetails);
|
||||||
|
|
||||||
public class ValidateCodeResult {
|
public class ValidateCodeResult {
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
|
|
|
@ -26,6 +26,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
import java.nio.file.FileVisitOption;
|
import java.nio.file.FileVisitOption;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -56,6 +57,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||||
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.ElementUtil;
|
import ca.uhn.fhir.util.ElementUtil;
|
||||||
|
@ -70,8 +72,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
private IFhirResourceDaoCodeSystem<CodeSystem, CodeableConcept, Coding> myCodeSystemDao;
|
private IFhirResourceDaoCodeSystem<CodeSystem, CodeableConcept, Coding> myCodeSystemDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueSet expand(IIdType theId, String theFilter) {
|
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||||
ValueSet source = myValidationSupport.fetchResource(getContext(), ValueSet.class, theId.getValue());
|
ValueSet source = read(theId, theRequestDetails);
|
||||||
return expand(source, theFilter);
|
return expand(source, theFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +88,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
||||||
|
|
||||||
ValueSet retVal = new ValueSet();
|
ValueSet retVal = new ValueSet();
|
||||||
|
retVal.getMeta().setLastUpdated(new Date());
|
||||||
retVal.setExpansion(expansion);
|
retVal.setExpansion(expansion);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +169,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
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) {
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
|
|
||||||
List<IIdType> valueSetIds = Collections.emptyList();
|
List<IIdType> valueSetIds = Collections.emptyList();
|
||||||
List<IIdType> codeSystemIds = Collections.emptyList();
|
List<IIdType> codeSystemIds = Collections.emptyList();
|
||||||
|
@ -205,7 +208,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IIdType nextId : valueSetIds) {
|
for (IIdType nextId : valueSetIds) {
|
||||||
ValueSet expansion = expand(nextId, null);
|
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
||||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
@ -219,7 +222,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IIdType nextId : codeSystemIds) {
|
for (IIdType nextId : codeSystemIds) {
|
||||||
ValueSet expansion = expand(nextId, null);
|
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
||||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ import javax.persistence.Index;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.PrePersist;
|
||||||
|
import javax.persistence.PreUpdate;
|
||||||
import javax.persistence.SequenceGenerator;
|
import javax.persistence.SequenceGenerator;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
@ -49,47 +52,56 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import org.apache.lucene.analysis.core.WhitespaceTokenizerFactory;
|
||||||
import org.hibernate.search.annotations.Analyze;
|
import org.hibernate.search.annotations.Analyze;
|
||||||
import org.hibernate.search.annotations.Analyzer;
|
import org.hibernate.search.annotations.Analyzer;
|
||||||
|
import org.hibernate.search.annotations.AnalyzerDef;
|
||||||
|
import org.hibernate.search.annotations.AnalyzerDefs;
|
||||||
import org.hibernate.search.annotations.Field;
|
import org.hibernate.search.annotations.Field;
|
||||||
import org.hibernate.search.annotations.Fields;
|
import org.hibernate.search.annotations.Fields;
|
||||||
import org.hibernate.search.annotations.Indexed;
|
import org.hibernate.search.annotations.Indexed;
|
||||||
import org.hibernate.search.annotations.Store;
|
import org.hibernate.search.annotations.Store;
|
||||||
|
import org.hibernate.search.annotations.TokenizerDef;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@Entity
|
@Entity
|
||||||
@Indexed()
|
@Indexed(interceptor=DeferConceptIndexingInterceptor.class)
|
||||||
@Table(name="TRM_CONCEPT", uniqueConstraints= {
|
@Table(name="TRM_CONCEPT", uniqueConstraints= {
|
||||||
@UniqueConstraint(name="IDX_CONCEPT_CS_CODE", columnNames= {"CODESYSTEM_PID", "CODE"})
|
@UniqueConstraint(name="IDX_CONCEPT_CS_CODE", columnNames= {"CODESYSTEM_PID", "CODE"})
|
||||||
}, indexes= {
|
}, indexes= {
|
||||||
@Index(name = "IDX_CONCEPT_INDEXSTATUS", columnList="INDEX_STATUS")
|
@Index(name = "IDX_CONCEPT_INDEXSTATUS", columnList="INDEX_STATUS")
|
||||||
})
|
})
|
||||||
|
@AnalyzerDefs({
|
||||||
|
@AnalyzerDef(name = "conceptParentPidsAnalyzer",
|
||||||
|
tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
|
||||||
|
filters = {
|
||||||
|
})
|
||||||
|
})
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class TermConcept implements Serializable {
|
public class TermConcept implements Serializable {
|
||||||
private static final int MAX_DESC_LENGTH = 400;
|
private static final int MAX_DESC_LENGTH = 400;
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class);
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@OneToMany(fetch=FetchType.LAZY, mappedBy="myParent")
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade= {})
|
||||||
private Collection<TermConceptParentChildLink> myChildren;
|
private Collection<TermConceptParentChildLink> myChildren;
|
||||||
|
|
||||||
@Column(name="CODE", length=100, nullable=false)
|
@Column(name = "CODE", length = 100, nullable = false)
|
||||||
@Fields({
|
@Fields({ @Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")), })
|
||||||
@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),
|
|
||||||
})
|
|
||||||
private String myCode;
|
private String myCode;
|
||||||
|
|
||||||
@ManyToOne()
|
@ManyToOne()
|
||||||
@JoinColumn(name="CODESYSTEM_PID", referencedColumnName="PID", foreignKey=@ForeignKey(name="FK_CONCEPT_PID_CS_PID"))
|
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
|
||||||
private TermCodeSystemVersion myCodeSystem;
|
private TermCodeSystemVersion myCodeSystem;
|
||||||
|
|
||||||
@Column(name="CODESYSTEM_PID", insertable=false, updatable=false)
|
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||||
@Fields({
|
@Fields({ @Field(name = "myCodeSystemVersionPid") })
|
||||||
@Field(name="myCodeSystemVersionPid")
|
|
||||||
})
|
|
||||||
private long myCodeSystemVersionPid;
|
private long myCodeSystemVersionPid;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@Column(name="DISPLAY", length=MAX_DESC_LENGTH, nullable=true)
|
@Column(name="DISPLAY", length=MAX_DESC_LENGTH, nullable=true)
|
||||||
@Fields({
|
@Fields({
|
||||||
|
@ -100,23 +112,21 @@ public class TermConcept implements Serializable {
|
||||||
})
|
})
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name="SEQ_CONCEPT_PID", sequenceName="SEQ_CONCEPT_PID")
|
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
||||||
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CONCEPT_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
||||||
@Column(name="PID")
|
@Column(name = "PID")
|
||||||
private Long myId;
|
private Long myId;
|
||||||
|
|
||||||
@Column(name = "INDEX_STATUS", nullable = true)
|
@Column(name = "INDEX_STATUS", nullable = true)
|
||||||
private Long myIndexStatus;
|
private Long myIndexStatus;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@Fields({
|
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "conceptParentPidsAnalyzer"))
|
||||||
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
|
||||||
})
|
|
||||||
private String myParentPids;
|
private String myParentPids;
|
||||||
|
|
||||||
@OneToMany(cascade= {}, fetch=FetchType.LAZY, mappedBy="myChild")
|
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myChild")
|
||||||
private Collection<TermConceptParentChildLink> myParents;
|
private Collection<TermConceptParentChildLink> myParents;
|
||||||
|
|
||||||
public TermConcept() {
|
public TermConcept() {
|
||||||
|
@ -135,7 +145,7 @@ public class TermConcept implements Serializable {
|
||||||
link.setChild(theChild);
|
link.setChild(theChild);
|
||||||
link.setRelationshipType(theRelationshipType);
|
link.setRelationshipType(theRelationshipType);
|
||||||
getChildren().add(link);
|
getChildren().add(link);
|
||||||
|
|
||||||
theChild.getParents().add(link);
|
theChild.getParents().add(link);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -154,8 +164,8 @@ public class TermConcept implements Serializable {
|
||||||
if (theObj == this) {
|
if (theObj == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TermConcept obj = (TermConcept)theObj;
|
TermConcept obj = (TermConcept) theObj;
|
||||||
|
|
||||||
EqualsBuilder b = new EqualsBuilder();
|
EqualsBuilder b = new EqualsBuilder();
|
||||||
b.append(myCodeSystem, obj.myCodeSystem);
|
b.append(myCodeSystem, obj.myCodeSystem);
|
||||||
|
@ -190,13 +200,17 @@ public class TermConcept implements Serializable {
|
||||||
return myIndexStatus;
|
return myIndexStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getParentPidsAsString() {
|
||||||
|
return myParentPids;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<TermConceptParentChildLink> getParents() {
|
public Collection<TermConceptParentChildLink> getParents() {
|
||||||
if (myParents == null) {
|
if (myParents == null) {
|
||||||
myParents = new ArrayList<TermConceptParentChildLink>();
|
myParents = new ArrayList<TermConceptParentChildLink>();
|
||||||
}
|
}
|
||||||
return myParents;
|
return myParents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
HashCodeBuilder b = new HashCodeBuilder();
|
HashCodeBuilder b = new HashCodeBuilder();
|
||||||
|
@ -204,7 +218,29 @@ public class TermConcept implements Serializable {
|
||||||
b.append(myCode);
|
b.append(myCode);
|
||||||
return b.toHashCode();
|
return b.toHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parentPids(TermConcept theNextConcept, Set<Long> theParentPids) {
|
||||||
|
for (TermConceptParentChildLink nextParentLink : theNextConcept.getParents()) {
|
||||||
|
TermConcept parent = nextParentLink.getParent();
|
||||||
|
Long parentConceptId = parent.getId();
|
||||||
|
Validate.notNull(parentConceptId);
|
||||||
|
if (parent != null && theParentPids.add(parentConceptId)) {
|
||||||
|
parentPids(parent, theParentPids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreUpdate
|
||||||
|
@PrePersist
|
||||||
|
public void prePersist() {
|
||||||
|
Set<Long> parentPids = new HashSet<Long>();
|
||||||
|
TermConcept entity = this;
|
||||||
|
parentPids(entity, parentPids);
|
||||||
|
entity.setParentPids(parentPids);
|
||||||
|
|
||||||
|
ourLog.trace("Code {}/{} has parents {}", entity.getId(), entity.getCode(), entity.getParentPidsAsString());
|
||||||
|
}
|
||||||
|
|
||||||
public void setCode(String theCode) {
|
public void setCode(String theCode) {
|
||||||
myCode = theCode;
|
myCode = theCode;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +272,11 @@ public class TermConcept implements Serializable {
|
||||||
}
|
}
|
||||||
b.append(next);
|
b.append(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b.length() == 0) {
|
||||||
|
b.append("NONE");
|
||||||
|
}
|
||||||
|
|
||||||
myParentPids = b.toString();
|
myParentPids = b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,5 +284,4 @@ public class TermConcept implements Serializable {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("code", myCode).append("display", myDisplay).build();
|
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("code", myCode).append("display", myDisplay).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,55 @@ public class TermConceptParentChildLink implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((myChild == null) ? 0 : myChild.hashCode());
|
||||||
|
result = prime * result + ((myCodeSystem == null) ? 0 : myCodeSystem.hashCode());
|
||||||
|
result = prime * result + ((myParent == null) ? 0 : myParent.hashCode());
|
||||||
|
result = prime * result + ((myRelationshipType == null) ? 0 : myRelationshipType.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
TermConceptParentChildLink other = (TermConceptParentChildLink) obj;
|
||||||
|
if (myChild == null) {
|
||||||
|
if (other.myChild != null)
|
||||||
|
return false;
|
||||||
|
} else if (!myChild.equals(other.myChild))
|
||||||
|
return false;
|
||||||
|
if (myCodeSystem == null) {
|
||||||
|
if (other.myCodeSystem != null)
|
||||||
|
return false;
|
||||||
|
} else if (!myCodeSystem.equals(other.myCodeSystem))
|
||||||
|
return false;
|
||||||
|
if (myParent == null) {
|
||||||
|
if (other.myParent != null)
|
||||||
|
return false;
|
||||||
|
} else if (!myParent.equals(other.myParent))
|
||||||
|
return false;
|
||||||
|
if (myRelationshipType != other.myRelationshipType)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum RelationshipTypeEnum{
|
public enum RelationshipTypeEnum{
|
||||||
|
// ********************************************
|
||||||
|
// IF YOU ADD HERE MAKE SURE ORDER IS PRESERVED
|
||||||
ISA
|
ISA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return myPid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
||||||
@IdParam(optional=true) IdDt theId,
|
@IdParam(optional=true) IdDt theId,
|
||||||
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
||||||
@OperationParam(name="identifier", min=0, max=1) UriDt theIdentifier,
|
@OperationParam(name="identifier", min=0, max=1) UriDt theIdentifier,
|
||||||
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter) {
|
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter,
|
||||||
|
RequestDetails theRequestDetails) {
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
boolean haveId = theId != null && theId.hasIdPart();
|
boolean haveId = theId != null && theId.hasIdPart();
|
||||||
|
@ -72,7 +73,7 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||||
if (haveId) {
|
if (haveId) {
|
||||||
return dao.expand(theId, toFilterString(theFilter));
|
return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
|
||||||
} else if (haveIdentifier) {
|
} else if (haveIdentifier) {
|
||||||
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,14 +156,15 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
||||||
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
|
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
|
||||||
@OperationParam(name="display", min=0, max=1) StringDt theDisplay,
|
@OperationParam(name="display", min=0, max=1) StringDt theDisplay,
|
||||||
@OperationParam(name="coding", min=0, max=1) CodingDt theCoding,
|
@OperationParam(name="coding", min=0, max=1) CodingDt theCoding,
|
||||||
@OperationParam(name="codeableConcept", min=0, max=1) CodeableConceptDt theCodeableConcept
|
@OperationParam(name="codeableConcept", min=0, max=1) CodeableConceptDt theCodeableConcept,
|
||||||
|
RequestDetails theRequestDetails
|
||||||
) {
|
) {
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||||
ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept);
|
ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
Parameters retVal = new Parameters();
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanDt(result.isResult()));
|
retVal.addParameter().setName("result").setValue(new BooleanDt(result.isResult()));
|
||||||
if (isNotBlank(result.getMessage())) {
|
if (isNotBlank(result.getMessage())) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDstu3<ValueSet> {
|
public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDstu3<ValueSet> {
|
||||||
|
@ -50,7 +51,8 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
||||||
@IdParam(optional=true) IdType theId,
|
@IdParam(optional=true) IdType theId,
|
||||||
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
||||||
@OperationParam(name="identifier", min=0, max=1) UriType theIdentifier,
|
@OperationParam(name="identifier", min=0, max=1) UriType theIdentifier,
|
||||||
@OperationParam(name = "filter", min=0, max=1) StringType theFilter) {
|
@OperationParam(name = "filter", min=0, max=1) StringType theFilter,
|
||||||
|
RequestDetails theRequestDetails) {
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
boolean haveId = theId != null && theId.hasIdPart();
|
boolean haveId = theId != null && theId.hasIdPart();
|
||||||
|
@ -69,7 +71,7 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||||
if (haveId) {
|
if (haveId) {
|
||||||
return dao.expand(theId, toFilterString(theFilter));
|
return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
|
||||||
} else if (haveIdentifier) {
|
} else if (haveIdentifier) {
|
||||||
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,14 +120,15 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
||||||
@OperationParam(name="system", min=0, max=1) UriType theSystem,
|
@OperationParam(name="system", min=0, max=1) UriType theSystem,
|
||||||
@OperationParam(name="display", min=0, max=1) StringType theDisplay,
|
@OperationParam(name="display", min=0, max=1) StringType theDisplay,
|
||||||
@OperationParam(name="coding", min=0, max=1) Coding theCoding,
|
@OperationParam(name="coding", min=0, max=1) Coding theCoding,
|
||||||
@OperationParam(name="codeableConcept", min=0, max=1) CodeableConcept theCodeableConcept
|
@OperationParam(name="codeableConcept", min=0, max=1) CodeableConcept theCodeableConcept,
|
||||||
|
RequestDetails theRequestDetails
|
||||||
) {
|
) {
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||||
ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept);
|
ValidateCodeResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||||
Parameters retVal = new Parameters();
|
Parameters retVal = new Parameters();
|
||||||
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
||||||
if (isNotBlank(result.getMessage())) {
|
if (isNotBlank(result.getMessage())) {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ca.uhn.fhir.jpa.search;
|
||||||
|
|
||||||
|
import org.hibernate.search.indexes.interceptor.EntityIndexingInterceptor;
|
||||||
|
import org.hibernate.search.indexes.interceptor.IndexingOverride;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
|
||||||
|
public class DeferConceptIndexingInterceptor implements EntityIndexingInterceptor<TermConcept> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexingOverride onAdd(TermConcept theEntity) {
|
||||||
|
if (theEntity.getIndexStatus() == null) {
|
||||||
|
return IndexingOverride.SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IndexingOverride.APPLY_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexingOverride onCollectionUpdate(TermConcept theEntity) {
|
||||||
|
return IndexingOverride.APPLY_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexingOverride onDelete(TermConcept theEntity) {
|
||||||
|
return IndexingOverride.APPLY_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexingOverride onUpdate(TermConcept theEntity) {
|
||||||
|
return onAdd(theEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.term;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
@ -32,10 +33,17 @@ import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import javax.persistence.PersistenceContextType;
|
import javax.persistence.PersistenceContextType;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import com.google.common.base.Stopwatch;
|
import com.google.common.base.Stopwatch;
|
||||||
|
|
||||||
|
@ -50,6 +58,8 @@ import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.ObjectUtil;
|
import ca.uhn.fhir.util.ObjectUtil;
|
||||||
|
@ -85,6 +95,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
protected EntityManager myEntityManager;
|
protected EntityManager myEntityManager;
|
||||||
|
|
||||||
private boolean myProcessDeferred = true;
|
private boolean myProcessDeferred = true;
|
||||||
|
private long myNextReindexPass;
|
||||||
|
|
||||||
private boolean addToSet(Set<TermConcept> theSetToPopulate, TermConcept theConcept) {
|
private boolean addToSet(Set<TermConcept> theSetToPopulate, TermConcept theConcept) {
|
||||||
boolean retVal = theSetToPopulate.add(theConcept);
|
boolean retVal = theSetToPopulate.add(theConcept);
|
||||||
|
@ -209,15 +220,6 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parentPids(TermConcept theNextConcept, Set<Long> theParentPids) {
|
|
||||||
for (TermConceptParentChildLink nextParentLink : theNextConcept.getParents()){
|
|
||||||
TermConcept parent = nextParentLink.getParent();
|
|
||||||
if (parent != null && theParentPids.add(parent.getId())) {
|
|
||||||
parentPids(parent, theParentPids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void persistChildren(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, IdentityHashMap<TermConcept, Object> theConceptsStack, int theTotalConcepts) {
|
private void persistChildren(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, IdentityHashMap<TermConcept, Object> theConceptsStack, int theTotalConcepts) {
|
||||||
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
||||||
return;
|
return;
|
||||||
|
@ -231,12 +233,8 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
theConcept.setCodeSystem(theCodeSystem);
|
theConcept.setCodeSystem(theCodeSystem);
|
||||||
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||||
|
|
||||||
Set<Long> parentPids = new HashSet<Long>();
|
|
||||||
parentPids(theConcept, parentPids);
|
|
||||||
theConcept.setParentPids(parentPids);
|
|
||||||
|
|
||||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||||
myConceptDao.save(theConcept);
|
saveConcept(theConcept);
|
||||||
} else {
|
} else {
|
||||||
myConceptsToSaveLater.add(theConcept);
|
myConceptsToSaveLater.add(theConcept);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +245,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
|
|
||||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||||
myConceptParentChildLinkDao.save(next);
|
saveConceptLink(next);
|
||||||
} else {
|
} else {
|
||||||
myConceptLinksToSaveLater.add(next);
|
myConceptLinksToSaveLater.add(next);
|
||||||
}
|
}
|
||||||
|
@ -255,6 +253,44 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveConceptLink(TermConceptParentChildLink next) {
|
||||||
|
if (next.getId() == null) {
|
||||||
|
myConceptParentChildLinkDao.save(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int saveConcept(TermConcept theConcept) {
|
||||||
|
int retVal = 0;
|
||||||
|
retVal += ensureParentsSaved(theConcept.getParents());
|
||||||
|
if (theConcept.getId() == null || theConcept.getIndexStatus() == null) {
|
||||||
|
retVal++;
|
||||||
|
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||||
|
myConceptDao.saveAndFlush(theConcept);
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.trace("Saved {} and got PID {}", theConcept.getCode(), theConcept.getId());
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ensureParentsSaved(Collection<TermConceptParentChildLink> theParents) {
|
||||||
|
ourLog.trace("Checking {} parents", theParents.size());
|
||||||
|
int retVal = 0;
|
||||||
|
|
||||||
|
for (TermConceptParentChildLink nextLink : theParents) {
|
||||||
|
if (nextLink.getRelationshipType() == RelationshipTypeEnum.ISA) {
|
||||||
|
TermConcept nextParent = nextLink.getParent();
|
||||||
|
retVal += ensureParentsSaved(nextParent.getParents());
|
||||||
|
if (nextParent.getId() == null) {
|
||||||
|
myConceptDao.saveAndFlush(nextParent);
|
||||||
|
retVal++;
|
||||||
|
ourLog.debug("Saved parent code {} and got id {}", nextParent.getCode(), nextParent.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
|
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
|
||||||
if (theNext.getCodeSystem() != null) {
|
if (theNext.getCodeSystem() != null) {
|
||||||
return;
|
return;
|
||||||
|
@ -270,30 +306,76 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void saveDeferred() {
|
public synchronized void saveDeferred() {
|
||||||
if (!myProcessDeferred || ((myConceptsToSaveLater.isEmpty() && myConceptLinksToSaveLater.isEmpty()))) {
|
if (!myProcessDeferred || ((myConceptsToSaveLater.isEmpty() && myConceptLinksToSaveLater.isEmpty()))) {
|
||||||
return;
|
processReindexing();
|
||||||
}
|
}
|
||||||
|
|
||||||
int codeCount = 0, relCount = 0;
|
int codeCount = 0, relCount = 0;
|
||||||
|
StopWatch stopwatch = new StopWatch();
|
||||||
|
|
||||||
int count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptsToSaveLater.size());
|
int count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptsToSaveLater.size());
|
||||||
ourLog.info("Saving {} deferred concepts...", count);
|
ourLog.info("Saving {} deferred concepts...", count);
|
||||||
while (codeCount < count && myConceptsToSaveLater.size() > 0) {
|
while (codeCount < count && myConceptsToSaveLater.size() > 0) {
|
||||||
TermConcept next = myConceptsToSaveLater.remove(0);
|
TermConcept next = myConceptsToSaveLater.remove(0);
|
||||||
myConceptDao.save(next);
|
codeCount += saveConcept(next);
|
||||||
codeCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (codeCount > 0) {
|
||||||
|
ourLog.info("Saved {} deferred concepts ({} codes remain and {} relationships remain) in {}ms ({}ms / code)", new Object[] {codeCount, myConceptsToSaveLater.size(), myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(codeCount)});
|
||||||
|
}
|
||||||
|
|
||||||
if (codeCount == 0) {
|
if (codeCount == 0) {
|
||||||
count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptLinksToSaveLater.size());
|
count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptLinksToSaveLater.size());
|
||||||
ourLog.info("Saving {} deferred concept relationships...", count);
|
ourLog.info("Saving {} deferred concept relationships...", count);
|
||||||
while (relCount < count && myConceptLinksToSaveLater.size() > 0) {
|
while (relCount < count && myConceptLinksToSaveLater.size() > 0) {
|
||||||
TermConceptParentChildLink next = myConceptLinksToSaveLater.remove(0);
|
TermConceptParentChildLink next = myConceptLinksToSaveLater.remove(0);
|
||||||
myConceptParentChildLinkDao.save(next);
|
saveConceptLink(next);
|
||||||
relCount++;
|
relCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Saved {} deferred concepts ({} remain) and {} deferred relationships ({} remain)", new Object[] {codeCount, myConceptsToSaveLater.size(), relCount, myConceptLinksToSaveLater.size()});
|
if (relCount > 0) {
|
||||||
|
ourLog.info("Saved {} deferred relationships ({} remain) in {}ms ({}ms / code)", new Object[] {relCount, myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(codeCount)});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((myConceptsToSaveLater.size() + myConceptLinksToSaveLater.size()) == 0) {
|
||||||
|
ourLog.info("All deferred concepts and relationships have now been synchronized to the database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlatformTransactionManager myTransactionMgr;
|
||||||
|
|
||||||
|
private void processReindexing() {
|
||||||
|
if (System.currentTimeMillis() < myNextReindexPass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionTemplate tt = new TransactionTemplate(myTransactionMgr);
|
||||||
|
tt.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||||
|
tt.execute(new TransactionCallbackWithoutResult() {
|
||||||
|
@Override
|
||||||
|
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
|
||||||
|
int maxResult = 1000;
|
||||||
|
Page<TermConcept> resources = myConceptDao.findResourcesRequiringReindexing(new PageRequest(0, maxResult));
|
||||||
|
if (resources.hasContent() == false) {
|
||||||
|
myNextReindexPass = System.currentTimeMillis() + DateUtils.MILLIS_PER_MINUTE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info("Indexing {} / {} concepts", resources.getContent().size(), resources.getTotalElements());
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
StopWatch stopwatch = new StopWatch();
|
||||||
|
|
||||||
|
for (TermConcept resourceTable : resources) {
|
||||||
|
saveConcept(resourceTable);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info("Indexed {} / {} concepts in {}ms - Avg {}ms / resource", new Object[] { count, resources.getContent().size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(count) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.QueryWrapperFilter;
|
||||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.FullTextQuery;
|
import org.hibernate.search.jpa.FullTextQuery;
|
||||||
import org.hibernate.search.query.dsl.BooleanJunction;
|
import org.hibernate.search.query.dsl.BooleanJunction;
|
||||||
|
@ -78,56 +79,38 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
||||||
@Autowired
|
@Autowired
|
||||||
private ValueSetExpander myValueSetExpander;
|
private ValueSetExpander myValueSetExpander;
|
||||||
|
|
||||||
@Override
|
private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set<String> addedCodes, TermConcept nextConcept) {
|
||||||
public List<VersionIndependentConcept> expandValueSet(String theValueSet) {
|
if (addedCodes.add(nextConcept.getCode())) {
|
||||||
ValueSet source = new ValueSet();
|
ValueSetExpansionContainsComponent contains = retVal.addContains();
|
||||||
source.getCompose().addImport(theValueSet);
|
contains.setCode(nextConcept.getCode());
|
||||||
try {
|
contains.setSystem(system);
|
||||||
ArrayList<VersionIndependentConcept> retVal = new ArrayList<VersionIndependentConcept>();
|
contains.setDisplay(nextConcept.getDisplay());
|
||||||
|
|
||||||
ValueSetExpansionOutcome outcome = myValueSetExpander.expand(source);
|
|
||||||
for (ValueSetExpansionContainsComponent next : outcome.getValueset().getExpansion().getContains()) {
|
|
||||||
retVal.add(new VersionIndependentConcept(next.getSystem(), next.getCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new InternalErrorException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void addDisplayFilterExact(QueryBuilder qb, BooleanJunction<?> bool, ConceptSetFilterComponent nextFilter) {
|
||||||
@Transactional(propagation=Propagation.REQUIRED)
|
bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery());
|
||||||
public void storeNewCodeSystemVersion(String theSystem, TermCodeSystemVersion theCodeSystemVersion, RequestDetails theRequestDetails) {
|
}
|
||||||
CodeSystem cs = new org.hl7.fhir.dstu3.model.CodeSystem();
|
|
||||||
cs.setUrl(theSystem);
|
|
||||||
cs.setContent(CodeSystemContentMode.NOTPRESENT);
|
|
||||||
|
|
||||||
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
|
|
||||||
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
|
|
||||||
if (createOutcome.getCreated() != Boolean.TRUE) {
|
|
||||||
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);
|
|
||||||
csId = myCodeSystemResourceDao.update(existing, theRequestDetails).getId();
|
|
||||||
|
|
||||||
ourLog.info("Created new version of CodeSystem, got ID: {}", csId.toUnqualified().getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceTable resource = (ResourceTable) myCodeSystemResourceDao.readEntity(csId);
|
|
||||||
Long codeSystemResourcePid = resource.getId();
|
|
||||||
|
|
||||||
ourLog.info("CodeSystem resource has ID: {}", csId.getValue());
|
|
||||||
|
|
||||||
theCodeSystemVersion.setResource(resource);
|
|
||||||
theCodeSystemVersion.setResourceVersionId(resource.getVersion());
|
|
||||||
super.storeNewCodeSystemVersion(codeSystemResourcePid, theSystem, theCodeSystemVersion);
|
|
||||||
|
|
||||||
|
private void addDisplayFilterInexact(QueryBuilder qb, BooleanJunction<?> bool, ConceptSetFilterComponent nextFilter) {
|
||||||
|
//@formatter:off
|
||||||
|
Query textQuery = qb
|
||||||
|
.phrase()
|
||||||
|
.withSlop(2)
|
||||||
|
.onField("myDisplay").boostedTo(4.0f)
|
||||||
|
.andField("myDisplayEdgeNGram").boostedTo(2.0f)
|
||||||
|
//.andField("myDisplayNGram").boostedTo(1.0f)
|
||||||
|
//.andField("myDisplayPhonetic").boostedTo(0.5f)
|
||||||
|
.sentence(nextFilter.getValue().toLowerCase()).createQuery();
|
||||||
|
bool.must(textQuery);
|
||||||
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||||
String system = theInclude.getSystem();
|
String system = theInclude.getSystem();
|
||||||
|
ourLog.info("Starting expansion around code system: {}", system);
|
||||||
|
|
||||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(system);
|
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(system);
|
||||||
TermCodeSystemVersion csv = cs.getCurrentVersion();
|
TermCodeSystemVersion csv = cs.getCurrentVersion();
|
||||||
|
|
||||||
|
@ -167,27 +150,40 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
||||||
bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery());
|
bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery());
|
||||||
|
|
||||||
for (ConceptSetFilterComponent nextFilter : theInclude.getFilter()) {
|
for (ConceptSetFilterComponent nextFilter : theInclude.getFilter()) {
|
||||||
if (nextFilter.getProperty().equals("display") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
if (isNotBlank(nextFilter.getValue())) {
|
||||||
if (isNotBlank(nextFilter.getValue())) {
|
if (nextFilter.getProperty().equals("display:exact") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||||
bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery());
|
addDisplayFilterExact(qb, bool, nextFilter);
|
||||||
}
|
} else if (nextFilter.getProperty().equals("display") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||||
} else if (nextFilter.getOp() == FilterOperator.ISA) {
|
if (nextFilter.getValue().trim().contains(" ")) {
|
||||||
if (isNotBlank(nextFilter.getValue())) {
|
addDisplayFilterExact(qb, bool, nextFilter);
|
||||||
|
} else {
|
||||||
|
addDisplayFilterInexact(qb, bool, nextFilter);
|
||||||
|
}
|
||||||
|
} else if ((nextFilter.getProperty().equals("concept") || nextFilter.getProperty().equals("code")) && nextFilter.getOp() == FilterOperator.ISA) {
|
||||||
TermConcept code = super.findCode(system, nextFilter.getValue());
|
TermConcept code = super.findCode(system, nextFilter.getValue());
|
||||||
|
if (code == null) {
|
||||||
|
throw new InvalidRequestException("Invalid filter criteria - code does not exist: {" + system + "}" + nextFilter.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
ourLog.info(" * Filtering on codes with a parent of {}/{}/{}", code.getId(), code.getCode(), code.getDisplay());
|
||||||
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Query luceneQuery = bool.createQuery();
|
Query luceneQuery = bool.createQuery();
|
||||||
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
||||||
|
jpaQuery.setMaxResults(1000);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<TermConcept> result = jpaQuery.getResultList();
|
List<TermConcept> result = jpaQuery.getResultList();
|
||||||
for (TermConcept nextConcept : result) {
|
for (TermConcept nextConcept : result) {
|
||||||
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retVal.setTotal(jpaQuery.getResultSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!haveIncludeCriteria) {
|
if (!haveIncludeCriteria) {
|
||||||
|
@ -196,19 +192,29 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
||||||
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retVal.setTotal(retVal.getContains().size());
|
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set<String> addedCodes, TermConcept nextConcept) {
|
@Override
|
||||||
if (addedCodes.add(nextConcept.getCode())) {
|
public List<VersionIndependentConcept> expandValueSet(String theValueSet) {
|
||||||
ValueSetExpansionContainsComponent contains = retVal.addContains();
|
ValueSet source = new ValueSet();
|
||||||
contains.setCode(nextConcept.getCode());
|
source.getCompose().addImport(theValueSet);
|
||||||
contains.setSystem(system);
|
try {
|
||||||
contains.setDisplay(nextConcept.getDisplay());
|
ArrayList<VersionIndependentConcept> retVal = new ArrayList<VersionIndependentConcept>();
|
||||||
|
|
||||||
|
ValueSetExpansionOutcome outcome = myValueSetExpander.expand(source);
|
||||||
|
for (ValueSetExpansionContainsComponent next : outcome.getValueset().getExpansion().getContains()) {
|
||||||
|
retVal.add(new VersionIndependentConcept(next.getSystem(), next.getCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InternalErrorException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -238,6 +244,33 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
||||||
return super.supportsSystem(theSystem);
|
return super.supportsSystem(theSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void storeNewCodeSystemVersion(String theSystem, TermCodeSystemVersion theCodeSystemVersion, RequestDetails theRequestDetails) {
|
||||||
|
CodeSystem cs = new org.hl7.fhir.dstu3.model.CodeSystem();
|
||||||
|
cs.setUrl(theSystem);
|
||||||
|
cs.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||||
|
|
||||||
|
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
|
||||||
|
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
|
||||||
|
if (createOutcome.getCreated() != Boolean.TRUE) {
|
||||||
|
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);
|
||||||
|
csId = myCodeSystemResourceDao.update(existing, theRequestDetails).getId();
|
||||||
|
|
||||||
|
ourLog.info("Created new version of CodeSystem, got ID: {}", csId.toUnqualified().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceTable resource = (ResourceTable) myCodeSystemResourceDao.readEntity(csId);
|
||||||
|
Long codeSystemResourcePid = resource.getId();
|
||||||
|
|
||||||
|
ourLog.info("CodeSystem resource has ID: {}", csId.getValue());
|
||||||
|
|
||||||
|
theCodeSystemVersion.setResource(resource);
|
||||||
|
theCodeSystemVersion.setResourceVersionId(resource.getVersion());
|
||||||
|
super.storeNewCodeSystemVersion(codeSystemResourcePid, theSystem, theCodeSystemVersion);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@CoverageIgnore
|
@CoverageIgnore
|
||||||
@Override
|
@Override
|
||||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||||
|
|
|
@ -24,15 +24,12 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -47,7 +44,6 @@ import org.apache.commons.csv.CSVFormat;
|
||||||
import org.apache.commons.csv.CSVParser;
|
import org.apache.commons.csv.CSVParser;
|
||||||
import org.apache.commons.csv.CSVRecord;
|
import org.apache.commons.csv.CSVRecord;
|
||||||
import org.apache.commons.csv.QuoteMode;
|
import org.apache.commons.csv.QuoteMode;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
@ -102,6 +98,8 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||||
}
|
}
|
||||||
ourLog.info(b.toString(), theConcept.getCode());
|
ourLog.info(b.toString(), theConcept.getCode());
|
||||||
childIter.remove();
|
childIter.remove();
|
||||||
|
nextChild.getParents().remove(next);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dropCircularRefs(nextChild, theChain, theCode2concept, theCircularCounter);
|
dropCircularRefs(nextChild, theChain, theCode2concept, theCircularCounter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,4 +32,14 @@ public class StopWatch {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMillis() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long retVal = now - myStarted;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMillisPerOperation(int theNumOperations) {
|
||||||
|
return ((double)getMillis()) / Math.max(1.0, theNumOperations);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
|
@ -25,7 +24,6 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.model.primitive.UriDt;
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
|
@ -58,7 +56,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +69,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -85,7 +83,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -99,7 +97,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = new StringDt("Systolic blood pressure at First encounterXXXX");
|
StringDt display = new StringDt("Systolic blood pressure at First encounterXXXX");
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -113,7 +111,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
StringDt display = new StringDt("Systolic blood pressure at First encounter");
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -127,7 +125,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -141,7 +139,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
StringDt display = null;
|
StringDt display = null;
|
||||||
CodingDt coding = null;
|
CodingDt coding = null;
|
||||||
CodeableConceptDt codeableConcept = null;
|
CodeableConceptDt codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -150,7 +148,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
public void testExpandById() throws IOException {
|
public void testExpandById() throws IOException {
|
||||||
String resp;
|
String resp;
|
||||||
|
|
||||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null);
|
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
@ -175,7 +173,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
* Filter with display name
|
* Filter with display name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -188,7 +186,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||||
* Filter with code
|
* Filter with code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"));
|
expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"), mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
@ -37,142 +38,25 @@ import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
private static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
|
||||||
private static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3TerminologyTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3TerminologyTest.class);
|
||||||
|
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";
|
||||||
|
|
||||||
@AfterClass
|
@After
|
||||||
public static void afterClassClearContext() {
|
public void after() {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Before
|
||||||
public void testCodeSystemWithDefinedCodes() {
|
public void before() {
|
||||||
//@formatter:off
|
myDaoConfig.setMaximumExpansionSize(5000);
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
|
||||||
codeSystem
|
|
||||||
.addConcept().setCode("A").setDisplay("Code A")
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA"))
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB"));
|
|
||||||
codeSystem
|
|
||||||
.addConcept().setCode("B").setDisplay("Code A")
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code AA"))
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB"));
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
|
||||||
|
|
||||||
Set<TermConcept> codes = myTermSvc.findCodesBelow(id.getIdPartAsLong(), id.getVersionIdPartAsLong(), "A");
|
|
||||||
assertThat(toCodes(codes), containsInAnyOrder("A", "AA", "AB"));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testSearchCodeInEmptyValueSet() {
|
|
||||||
ValueSet valueSet = new ValueSet();
|
|
||||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
|
||||||
myValueSetDao.create(valueSet, mySrd);
|
|
||||||
|
|
||||||
Observation obsAA = new Observation();
|
|
||||||
obsAA.setStatus(ObservationStatus.FINAL);
|
|
||||||
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
|
||||||
myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsBA = new Observation();
|
|
||||||
obsBA.setStatus(ObservationStatus.FINAL);
|
|
||||||
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
|
||||||
myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsCA = new Observation();
|
|
||||||
obsCA.setStatus(ObservationStatus.FINAL);
|
|
||||||
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
|
||||||
myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchParameterMap params;
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
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 testSearchCodeInLocalCodesystem() {
|
|
||||||
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(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue(), idBA.getValue()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeInExternalCodesystem() {
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
Observation obsPA = new Observation();
|
|
||||||
obsPA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("ParentA");
|
|
||||||
IIdType idPA = myObservationDao.create(obsPA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsAAA = new Observation();
|
|
||||||
obsAAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("childAAA");
|
|
||||||
IIdType idAAA = myObservationDao.create(obsAAA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsAAB = new Observation();
|
|
||||||
obsAAB.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("childAAB");
|
|
||||||
IIdType idAAB = myObservationDao.create(obsAAB, 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, "childAA").setModifier(TokenParamModifier.BELOW));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAAA.getValue(), idAAB.getValue()));
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.ABOVE));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idPA.getValue()));
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idPA.getValue(), idAAA.getValue(), idAAB.getValue()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void createExternalCsAndLocalVs() {
|
|
||||||
CodeSystem codeSystem = createExternalCs();
|
|
||||||
|
|
||||||
createLocalVs(codeSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private CodeSystem createExternalCs() {
|
private CodeSystem createExternalCs() {
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
@ -203,179 +87,97 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||||
cs.getConcepts().add(parentB);
|
cs.getConcepts().add(parentB);
|
||||||
|
|
||||||
|
TermConcept childBA = new TermConcept(cs, "childBA").setDisplay("Child BA");
|
||||||
|
childBA.addChild(childAAB, RelationshipTypeEnum.ISA);
|
||||||
|
parentB.addChild(childBA, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept parentC = new TermConcept(cs, "ParentC").setDisplay("Parent C");
|
||||||
|
cs.getConcepts().add(parentC);
|
||||||
|
|
||||||
|
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
|
||||||
|
parentC.addChild(childCA, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs);
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs);
|
||||||
return codeSystem;
|
return codeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createExternalCsAndLocalVs() {
|
||||||
|
CodeSystem codeSystem = createExternalCs();
|
||||||
|
|
||||||
|
createLocalVs(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLocalCsAndVs() {
|
||||||
|
//@formatter:off
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("A").setDisplay("Code A")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AAA").setDisplay("Code AAA"))
|
||||||
|
)
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB"));
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("B").setDisplay("Code B")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
|
||||||
|
//@formatter:on
|
||||||
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
|
|
||||||
|
createLocalVs(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createLocalVs(CodeSystem codeSystem) {
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl());
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeBelowAndAboveUnknownCodeSystem() {
|
public void testCodeSystemCreateDuplicateFails() {
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
try {
|
||||||
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCodeSystemWithDefinedCodes() {
|
||||||
|
//@formatter:off
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("A").setDisplay("Code A")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA"))
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB"));
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("B").setDisplay("Code A")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code AA"))
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.BELOW));
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
Set<TermConcept> codes = myTermSvc.findCodesBelow(id.getIdPartAsLong(), id.getVersionIdPartAsLong(), "A");
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.ABOVE));
|
assertThat(toCodes(codes), containsInAnyOrder("A", "AA", "AB"));
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeInFhirCodesystem() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
AuditEvent aeIn1 = new AuditEvent();
|
|
||||||
aeIn1.getType().setSystem("http://nema.org/dicom/dicm").setCode("110102");
|
|
||||||
IIdType idIn1 = myAuditEventDao.create(aeIn1, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
AuditEvent aeIn2 = new AuditEvent();
|
|
||||||
aeIn2.getType().setSystem("http://hl7.org/fhir/audit-event-type").setCode("rest");
|
|
||||||
IIdType idIn2 = myAuditEventDao.create(aeIn2, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
AuditEvent aeOut1 = new AuditEvent();
|
|
||||||
aeOut1.getType().setSystem("http://example.com").setCode("foo");
|
|
||||||
IIdType idOut1 = myAuditEventDao.create(aeOut1, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/audit-event-type").setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), containsInAnyOrder(idIn1.getValue(), idIn2.getValue()));
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/v3-PurposeOfUse").setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Can't currently abort costly
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testRefuseCostlyExpansionFhirCodesystem() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
myDaoConfig.setMaximumExpansionSize(1);
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/audit-event-type").setModifier(TokenParamModifier.IN));
|
|
||||||
try {
|
|
||||||
myAuditEventDao.search(params);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRefuseCostlyExpansionLocalCodesystem() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
myDaoConfig.setMaximumExpansionSize(1);
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.ABOVE));
|
|
||||||
try {
|
|
||||||
myObservationDao.search(params);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("Expansion of ValueSet produced too many codes (maximum 1) - Operation aborted!", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithSystemAndCodesInLocalValueSet() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
include.addConcept().setCode("A");
|
|
||||||
include.addConcept().setCode("AA");
|
|
||||||
include.addConcept().setCode("AAA");
|
|
||||||
include.addConcept().setCode("AB");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
|
|
||||||
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("A", "AA", "AAA", "AB"));
|
|
||||||
|
|
||||||
int idx = codes.indexOf("AAA");
|
|
||||||
assertEquals("AAA", result.getExpansion().getContains().get(idx).getCode());
|
|
||||||
assertEquals("Code AAA", result.getExpansion().getContains().get(idx).getDisplay());
|
|
||||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
|
||||||
// ValueSet expansion = myValueSetDao.expandByIdentifier(URL_MY_VALUE_SET, "cervical");
|
|
||||||
// ValueSet expansion = myValueSetDao.expandByIdentifier(URL_MY_VALUE_SET, "cervical");
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithSystemAndCodesAndFilterInExternalValueSet() {
|
|
||||||
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");
|
|
||||||
|
|
||||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
|
|
||||||
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA", "ParentB"));
|
|
||||||
|
|
||||||
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 testIndexingIsDeferredForLargeCodeSystems() {
|
|
||||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
|
||||||
|
|
||||||
myTermSvc.setProcessDeferred(false);
|
|
||||||
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
|
|
||||||
include.addFilter().setProperty("display").setOp(FilterOperator.ISA).setValue("ParentA");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
assertEquals(0, result.getExpansion().getContains().size());
|
|
||||||
|
|
||||||
myTermSvc.setProcessDeferred(true);
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
|
|
||||||
result = myValueSetDao.expand(vs, null);
|
|
||||||
encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
assertEquals(4, result.getExpansion().getContains().size());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithExcludeInExternalValueSet() {
|
public void testExpandWithExcludeInExternalValueSet() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
|
@ -395,8 +197,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB"));
|
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -421,34 +222,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
// include.addConcept().setCode("A");
|
|
||||||
// include.addConcept().setCode("AA");
|
|
||||||
// include.addConcept().setCode("AAA");
|
|
||||||
// include.addConcept().setCode("AB");
|
|
||||||
|
|
||||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("AAA");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
|
|
||||||
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("AAA"));
|
|
||||||
|
|
||||||
assertEquals("AAA", result.getExpansion().getContains().get(0).getCode());
|
|
||||||
assertEquals("Code AAA", result.getExpansion().getContains().get(0).getDisplay());
|
|
||||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(0).getSystem());
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithNoResultsInLocalValueSet1() {
|
public void testExpandWithNoResultsInLocalValueSet1() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
|
@ -484,14 +257,202 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> toCodesContains(List<ValueSetExpansionContainsComponent> theContains) {
|
|
||||||
ArrayList<String> retVal = new ArrayList<String>();
|
|
||||||
for (ValueSetExpansionContainsComponent next : theContains) {
|
@Test
|
||||||
retVal.add(next.getCode());
|
public void testExpandWithSystemAndCodesAndFilterInExternalValueSet() {
|
||||||
}
|
createExternalCsAndLocalVs();
|
||||||
return retVal;
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
|
||||||
|
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA", "ParentB"));
|
||||||
|
|
||||||
|
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 testExpandWithDisplayInExternalValueSetFuzzyMatching() {
|
||||||
|
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 a");
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentA"));
|
||||||
|
|
||||||
|
vs = new ValueSet();
|
||||||
|
include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("pare");
|
||||||
|
result = myValueSetDao.expand(vs, null);
|
||||||
|
encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "ParentC"));
|
||||||
|
|
||||||
|
vs = new ValueSet();
|
||||||
|
include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setProperty("display:exact").setOp(FilterOperator.EQUAL).setValue("pare");
|
||||||
|
result = myValueSetDao.expand(vs, null);
|
||||||
|
encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
// include.addConcept().setCode("A");
|
||||||
|
// include.addConcept().setCode("AA");
|
||||||
|
// include.addConcept().setCode("AAA");
|
||||||
|
// include.addConcept().setCode("AB");
|
||||||
|
|
||||||
|
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("AAA");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
|
||||||
|
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("AAA"));
|
||||||
|
|
||||||
|
assertEquals("AAA", result.getExpansion().getContains().get(0).getCode());
|
||||||
|
assertEquals("Code AAA", result.getExpansion().getContains().get(0).getDisplay());
|
||||||
|
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(0).getSystem());
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithSystemAndCodesInLocalValueSet() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("A");
|
||||||
|
include.addConcept().setCode("AA");
|
||||||
|
include.addConcept().setCode("AAA");
|
||||||
|
include.addConcept().setCode("AB");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
|
||||||
|
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("A", "AA", "AAA", "AB"));
|
||||||
|
|
||||||
|
int idx = codes.indexOf("AAA");
|
||||||
|
assertEquals("AAA", result.getExpansion().getContains().get(idx).getCode());
|
||||||
|
assertEquals("Code AAA", result.getExpansion().getContains().get(idx).getDisplay());
|
||||||
|
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
||||||
|
// ValueSet expansion = myValueSetDao.expandByIdentifier(URL_MY_VALUE_SET, "cervical");
|
||||||
|
// ValueSet expansion = myValueSetDao.expandByIdentifier(URL_MY_VALUE_SET, "cervical");
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIndexingIsDeferredForLargeCodeSystems() {
|
||||||
|
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
||||||
|
|
||||||
|
myTermSvc.setProcessDeferred(false);
|
||||||
|
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("ParentA");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertEquals(0, result.getExpansion().getContains().size());
|
||||||
|
|
||||||
|
myTermSvc.setProcessDeferred(true);
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
|
||||||
|
vs = new ValueSet();
|
||||||
|
include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("ParentA");
|
||||||
|
result = myValueSetDao.expand(vs, null);
|
||||||
|
encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
assertEquals(4, result.getExpansion().getContains().size());
|
||||||
|
|
||||||
|
assertThat(encoded, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can't currently abort costly
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testRefuseCostlyExpansionFhirCodesystem() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
myDaoConfig.setMaximumExpansionSize(1);
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/audit-event-type").setModifier(TokenParamModifier.IN));
|
||||||
|
try {
|
||||||
|
myAuditEventDao.search(params);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRefuseCostlyExpansionLocalCodesystem() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
myDaoConfig.setMaximumExpansionSize(1);
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.ABOVE));
|
||||||
|
try {
|
||||||
|
myObservationDao.search(params);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Expansion of ValueSet produced too many codes (maximum 1) - Operation aborted!", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeAboveLocalCodesystem() {
|
public void testSearchCodeAboveLocalCodesystem() {
|
||||||
|
@ -519,16 +480,23 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Test
|
||||||
public void before() {
|
public void testSearchCodeBelowAndAboveUnknownCodeSystem() {
|
||||||
myDaoConfig.setMaximumExpansionSize(5000);
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.ABOVE));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
|
||||||
public void after() {
|
|
||||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeBelowLocalCodesystem() {
|
public void testSearchCodeBelowLocalCodesystem() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
|
@ -555,52 +523,134 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLocalCsAndVs() {
|
@Test
|
||||||
//@formatter:off
|
@Ignore
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
public void testSearchCodeInEmptyValueSet() {
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
ValueSet valueSet = new ValueSet();
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
codeSystem
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
.addConcept().setCode("A").setDisplay("Code A")
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA")
|
Observation obsAA = new Observation();
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("AAA").setDisplay("Code AAA"))
|
obsAA.setStatus(ObservationStatus.FINAL);
|
||||||
)
|
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB"));
|
myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
codeSystem
|
|
||||||
.addConcept().setCode("B").setDisplay("Code B")
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
|
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
|
|
||||||
//@formatter:on
|
|
||||||
myCodeSystemDao.create(codeSystem, mySrd);
|
|
||||||
|
|
||||||
createLocalVs(codeSystem);
|
Observation obsBA = new Observation();
|
||||||
|
obsBA.setStatus(ObservationStatus.FINAL);
|
||||||
|
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
||||||
|
myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsCA = new Observation();
|
||||||
|
obsCA.setStatus(ObservationStatus.FINAL);
|
||||||
|
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
||||||
|
myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap params;
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
Observation obsPA = new Observation();
|
||||||
|
obsPA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("ParentA");
|
||||||
|
IIdType idPA = myObservationDao.create(obsPA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsAAA = new Observation();
|
||||||
|
obsAAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("childAAA");
|
||||||
|
IIdType idAAA = myObservationDao.create(obsAAA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsAAB = new Observation();
|
||||||
|
obsAAB.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("childAAB");
|
||||||
|
IIdType idAAB = myObservationDao.create(obsAAB, 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, "childAA").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAAA.getValue(), idAAB.getValue()));
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "childAA").setModifier(TokenParamModifier.ABOVE));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idPA.getValue()));
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idPA.getValue(), idAAA.getValue(), idAAB.getValue()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeInFhirCodesystem() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
AuditEvent aeIn1 = new AuditEvent();
|
||||||
|
aeIn1.getType().setSystem("http://nema.org/dicom/dicm").setCode("110102");
|
||||||
|
IIdType idIn1 = myAuditEventDao.create(aeIn1, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
AuditEvent aeIn2 = new AuditEvent();
|
||||||
|
aeIn2.getType().setSystem("http://hl7.org/fhir/audit-event-type").setCode("rest");
|
||||||
|
IIdType idIn2 = myAuditEventDao.create(aeIn2, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
AuditEvent aeOut1 = new AuditEvent();
|
||||||
|
aeOut1.getType().setSystem("http://example.com").setCode("foo");
|
||||||
|
IIdType idOut1 = myAuditEventDao.create(aeOut1, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/audit-event-type").setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), containsInAnyOrder(idIn1.getValue(), idIn2.getValue()));
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/v3-PurposeOfUse").setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeInLocalCodesystem() {
|
||||||
|
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(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue(), idBA.getValue()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createLocalVs(CodeSystem codeSystem) {
|
private ArrayList<String> toCodesContains(List<ValueSetExpansionContainsComponent> theContains) {
|
||||||
ValueSet valueSet = new ValueSet();
|
ArrayList<String> retVal = new ArrayList<String>();
|
||||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
for (ValueSetExpansionContainsComponent next : theContains) {
|
||||||
valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl());
|
retVal.add(next.getCode());
|
||||||
myValueSetDao.create(valueSet, mySrd);
|
}
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@AfterClass
|
||||||
public void testCodeSystemCreateDuplicateFails() {
|
public static void afterClassClearContext() {
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
|
||||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
|
||||||
|
|
||||||
codeSystem = new CodeSystem();
|
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
|
||||||
try {
|
|
||||||
myCodeSystemDao.create(codeSystem, mySrd);
|
|
||||||
fail();
|
|
||||||
} catch (UnprocessableEntityException e) {
|
|
||||||
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import org.junit.Test;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
|
@ -62,7 +61,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -89,7 +88,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -103,7 +102,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertFalse(result.isResult());
|
assertFalse(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -117,7 +116,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = new StringType("Systolic blood pressure at First encounter");
|
StringType display = new StringType("Systolic blood pressure at First encounter");
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -132,7 +131,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = new CodeableConcept();
|
CodeableConcept codeableConcept = new CodeableConcept();
|
||||||
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -146,7 +145,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
StringType display = null;
|
StringType display = null;
|
||||||
Coding coding = null;
|
Coding coding = null;
|
||||||
CodeableConcept codeableConcept = null;
|
CodeableConcept codeableConcept = null;
|
||||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||||
assertTrue(result.isResult());
|
assertTrue(result.isResult());
|
||||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||||
}
|
}
|
||||||
|
@ -155,7 +154,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
public void testExpandById() throws IOException {
|
public void testExpandById() throws IOException {
|
||||||
String resp;
|
String resp;
|
||||||
|
|
||||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null);
|
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
|
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
|
||||||
|
@ -176,7 +175,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||||
* Filter with display name
|
* Filter with display name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
|
|
@ -24,7 +24,6 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.model.primitive.UriDt;
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test {
|
public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test {
|
||||||
|
@ -251,7 +250,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
|
||||||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package ca.uhn.fhir.jpa.provider.dstu3;
|
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest.*;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@ -12,25 +15,33 @@ import java.io.IOException;
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
import org.hl7.fhir.dstu3.model.CodeType;
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
import org.hl7.fhir.dstu3.model.Coding;
|
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3Test {
|
public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3Test {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3ValueSetTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3ValueSetTest.class);
|
||||||
private IIdType myExtensionalVsId;
|
private IIdType myExtensionalVsId;
|
||||||
|
private IIdType myLocalValueSetId;
|
||||||
|
private ValueSet myLocalVs;
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
|
@ -78,6 +89,140 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandLocalVsAgainstExternalCs() throws IOException {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Parameters respParam = ourClient
|
||||||
|
.operation()
|
||||||
|
.onInstance(myLocalValueSetId)
|
||||||
|
.named("expand")
|
||||||
|
.withNoParameters(Parameters.class)
|
||||||
|
.execute();
|
||||||
|
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
|
ourLog.info(resp);
|
||||||
|
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAA\"/>"));
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||||
|
assertThat(resp, not(containsStringIgnoringCase("<code value=\"ParentA\"/>")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandLocalVsWithUnknownCode() throws IOException {
|
||||||
|
createExternalCsAndLocalVsWithUnknownCode();
|
||||||
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
try {
|
||||||
|
ourClient
|
||||||
|
.operation()
|
||||||
|
.onInstance(myLocalValueSetId)
|
||||||
|
.named("expand")
|
||||||
|
.withNoParameters(Parameters.class)
|
||||||
|
.execute();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("HTTP 400 Bad Request: Invalid filter criteria - code does not exist: {http://example.com/my_code_system}childFOOOOOOO", e.getMessage());
|
||||||
|
}
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandInlineVsAgainstBuiltInCs() throws IOException {
|
||||||
|
createLocalVsPointingAtBuiltInCodeSystem();
|
||||||
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Parameters respParam = ourClient
|
||||||
|
.operation()
|
||||||
|
.onType(ValueSet.class)
|
||||||
|
.named("expand")
|
||||||
|
.withParameter(Parameters.class, "valueSet", myLocalVs)
|
||||||
|
.execute();
|
||||||
|
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
|
ourLog.info(resp);
|
||||||
|
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"M\"/>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandLocalVsAgainstBuiltInCs() throws IOException {
|
||||||
|
createLocalVsPointingAtBuiltInCodeSystem();
|
||||||
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Parameters respParam = ourClient
|
||||||
|
.operation()
|
||||||
|
.onInstance(myLocalValueSetId)
|
||||||
|
.named("expand")
|
||||||
|
.withNoParameters(Parameters.class)
|
||||||
|
.execute();
|
||||||
|
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
|
ourLog.info(resp);
|
||||||
|
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"M\"/>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandLocalVsCanonicalAgainstExternalCs() throws IOException {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Parameters respParam = ourClient
|
||||||
|
.operation()
|
||||||
|
.onType(ValueSet.class)
|
||||||
|
.named("expand")
|
||||||
|
.withParameter(Parameters.class, "identifier", new UriType(URL_MY_VALUE_SET))
|
||||||
|
.execute();
|
||||||
|
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
|
ourLog.info(resp);
|
||||||
|
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAA\"/>"));
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||||
|
assertThat(resp, not(containsStringIgnoringCase("<code value=\"ParentA\"/>")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandInlineVsAgainstExternalCs() throws IOException {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
assertNotNull(myLocalVs);
|
||||||
|
myLocalVs.setId("");
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
Parameters respParam = ourClient
|
||||||
|
.operation()
|
||||||
|
.onType(ValueSet.class)
|
||||||
|
.named("expand")
|
||||||
|
.withParameter(Parameters.class, "valueSet", myLocalVs)
|
||||||
|
.execute();
|
||||||
|
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||||
|
ourLog.info(resp);
|
||||||
|
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAA\"/>"));
|
||||||
|
assertThat(resp, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||||
|
assertThat(resp, not(containsStringIgnoringCase("<code value=\"ParentA\"/>")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandByIdWithFilter() throws IOException {
|
public void testExpandByIdWithFilter() throws IOException {
|
||||||
|
|
||||||
|
@ -231,4 +376,102 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
assertEquals(true, ((BooleanType)respParam.getParameter().get(0).getValue()).booleanValue());
|
assertEquals(true, ((BooleanType)respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private CodeSystem createExternalCs() {
|
||||||
|
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 parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||||
|
cs.getConcepts().add(parentA);
|
||||||
|
|
||||||
|
TermConcept childAA = new TermConcept(cs, "childAA").setDisplay("Child AA");
|
||||||
|
parentA.addChild(childAA, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept childAAA = new TermConcept(cs, "childAAA").setDisplay("Child AAA");
|
||||||
|
childAA.addChild(childAAA, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept childAAB = new TermConcept(cs, "childAAB").setDisplay("Child AAB");
|
||||||
|
childAA.addChild(childAAB, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept childAB = new TermConcept(cs, "childAB").setDisplay("Child AB");
|
||||||
|
parentA.addChild(childAB, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||||
|
cs.getConcepts().add(parentB);
|
||||||
|
|
||||||
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs);
|
||||||
|
return codeSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createExternalCsAndLocalVs() {
|
||||||
|
CodeSystem codeSystem = createExternalCs();
|
||||||
|
|
||||||
|
createLocalVs(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createExternalCsAndLocalVsWithUnknownCode() {
|
||||||
|
CodeSystem codeSystem = createExternalCs();
|
||||||
|
|
||||||
|
createLocalVsWithUnknownCode(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLocalCsAndVs() {
|
||||||
|
//@formatter:off
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("A").setDisplay("Code A")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AAA").setDisplay("Code AAA"))
|
||||||
|
)
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB"));
|
||||||
|
codeSystem
|
||||||
|
.addConcept().setCode("B").setDisplay("Code B")
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
|
||||||
|
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
|
||||||
|
//@formatter:on
|
||||||
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
|
|
||||||
|
createLocalVs(codeSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createLocalVs(CodeSystem codeSystem) {
|
||||||
|
myLocalVs = new ValueSet();
|
||||||
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
|
include.setSystem(codeSystem.getUrl());
|
||||||
|
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("childAA");
|
||||||
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLocalVsWithUnknownCode(CodeSystem codeSystem) {
|
||||||
|
myLocalVs = new ValueSet();
|
||||||
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
|
include.setSystem(codeSystem.getUrl());
|
||||||
|
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("childFOOOOOOO");
|
||||||
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLocalVsPointingAtBuiltInCodeSystem() {
|
||||||
|
myLocalVs = new ValueSet();
|
||||||
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
|
include.setSystem("http://hl7.org/fhir/v3/MaritalStatus");
|
||||||
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,6 +367,19 @@ public class SystemProviderDstu3Test extends BaseJpaDstu3Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMarkResourcesForReindexing() throws Exception {
|
||||||
|
HttpGet get = new HttpGet(ourServerBase + "/$mark-all-resources-for-reindexing");
|
||||||
|
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||||
|
try {
|
||||||
|
String output = IOUtils.toString(http.getEntity().getContent());
|
||||||
|
ourLog.info(output);
|
||||||
|
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(http);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.NEVER)
|
@Transactional(propagation = Propagation.NEVER)
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestKeywords() throws Exception {
|
public void testSuggestKeywords() throws Exception {
|
||||||
|
|
|
@ -30,10 +30,6 @@ public class TerminologyLoaderSvcIntegrationTest extends BaseJpaDstu3Test {
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void testLoadAndStoreSnomedCt() {
|
public void testLoadAndStoreSnomedCt() {
|
||||||
Map<String, File> files = new HashMap<String, File>();
|
|
||||||
files.put(TerminologyLoaderSvc.SCT_FILE_CONCEPT, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Concept_Full_INT_20160131.txt"));
|
|
||||||
files.put(TerminologyLoaderSvc.SCT_FILE_DESCRIPTION, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Description_Full-en_INT_20160131.txt"));
|
|
||||||
files.put(TerminologyLoaderSvc.SCT_FILE_RELATIONSHIP, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Relationship_Full_INT_20160131.txt"));
|
|
||||||
// myLoader.processSnomedCtFiles(files, mySrd);
|
// myLoader.processSnomedCtFiles(files, mySrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package ca.uhn.fhir.jpa.term;
|
package ca.uhn.fhir.jpa.term;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.contains;
|
|
||||||
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -25,6 +25,7 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
@ -79,6 +80,21 @@ public class TerminologyLoaderSvcTest {
|
||||||
mySvc.loadLoinc(list(bos1.toByteArray(), bos2.toByteArray()), details);
|
mySvc.loadLoinc(list(bos1.toByteArray(), bos2.toByteArray()), details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is just for trying stuff, it won't run without
|
||||||
|
* local files external to the git repo
|
||||||
|
*/
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testLoadSnomedCtAgainstRealFile() throws Exception {
|
||||||
|
byte[] bytes = IOUtils.toByteArray(new FileInputStream("/Users/james/Downloads/SnomedCT_Release_INT_20160131_Full.zip"));
|
||||||
|
|
||||||
|
RequestDetails details = mock(RequestDetails.class);
|
||||||
|
mySvc.loadSnomedCt(list(bytes), details);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadSnomedCt() throws Exception {
|
public void testLoadSnomedCt() throws Exception {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
|
|
@ -17,3 +17,4 @@ id effectiveTime active moduleId definitionStatusId
|
||||||
207527008 20020131 1 900000000000207008 900000000000074008
|
207527008 20020131 1 900000000000207008 900000000000074008
|
||||||
207527008 20040731 1 900000000000207008 900000000000073002
|
207527008 20040731 1 900000000000207008 900000000000073002
|
||||||
207527008 20090731 0 900000000000207008 900000000000074008
|
207527008 20090731 0 900000000000207008 900000000000074008
|
||||||
|
404684003 20040131 1 900000000000207008 900000000000074008
|
||||||
|
|
|
@ -67,6 +67,8 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
|
||||||
ValueSetExpansionOutcome vso;
|
ValueSetExpansionOutcome vso;
|
||||||
try {
|
try {
|
||||||
vso = getExpander().expand(theSource);
|
vso = getExpander().expand(theSource);
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new InternalErrorException(e);
|
throw new InternalErrorException(e);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +127,9 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueSetExpander getExpander() {
|
public ValueSetExpander getExpander() {
|
||||||
return new ValueSetExpanderSimple(this, this);
|
ValueSetExpanderSimple retVal = new ValueSetExpanderSimple(this, this);
|
||||||
|
retVal.setMaxExpansionSize(Integer.MAX_VALUE);
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -70,8 +70,10 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
private Set<String> excludeKeys = new HashSet<String>();
|
private Set<String> excludeKeys = new HashSet<String>();
|
||||||
private ValueSetExpanderFactory factory;
|
private ValueSetExpanderFactory factory;
|
||||||
private ValueSet focus;
|
private ValueSet focus;
|
||||||
|
private int maxExpansionSize = 500;
|
||||||
|
|
||||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||||
|
private int total;
|
||||||
|
|
||||||
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
||||||
super();
|
super();
|
||||||
|
@ -79,6 +81,10 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
||||||
|
maxExpansionSize = theMaxExpansionSize;
|
||||||
|
}
|
||||||
|
|
||||||
private void addCode(String system, String code, String display) {
|
private void addCode(String system, String code, String display) {
|
||||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||||
n.setSystem(system);
|
n.setSystem(system);
|
||||||
|
@ -101,7 +107,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) throws ETooCostly {
|
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) throws ETooCostly {
|
||||||
if (expand.getContains().size() > 500)
|
if (expand.getContains().size() > maxExpansionSize)
|
||||||
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
||||||
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
||||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||||
|
@ -111,6 +117,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||||
addCode(c.getSystem(), c.getCode(), c.getDisplay());
|
addCode(c.getSystem(), c.getCode(), c.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
total = expand.getTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void excludeCode(String theSystem, String theCode) {
|
private void excludeCode(String theSystem, String theCode) {
|
||||||
|
@ -171,6 +179,11 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
focus.getExpansion().getContains().add(c);
|
focus.getExpansion().getContains().add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (total > 0) {
|
||||||
|
focus.getExpansion().setTotal(total);
|
||||||
|
}
|
||||||
|
|
||||||
return new ValueSetExpansionOutcome(focus, null);
|
return new ValueSetExpansionOutcome(focus, null);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// TODO: we should put something more specific instead of just Exception below, since
|
// TODO: we should put something more specific instead of just Exception below, since
|
||||||
|
|
Loading…
Reference in New Issue