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")
|
||||
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();
|
||||
retVal.setContext(defaultFhirContext());
|
||||
retVal.setDao(systemDaoDstu3());
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -1174,7 +1174,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
coordsParams = extractSearchParamCoords(theEntity, theResource);
|
||||
|
||||
// ourLog.info("Indexing resource: {}", entity.getId());
|
||||
ourLog.info("Storing date indexes: {}", dateParams);
|
||||
ourLog.trace("Storing date indexes: {}", dateParams);
|
||||
|
||||
tokenParams = new HashSet<ResourceIndexedSearchParamToken>();
|
||||
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.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.TransactionStatus;
|
||||
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.entity.ForcedId;
|
||||
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.StopWatch;
|
||||
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);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
|
||||
int retVal = doPerformReindexingPassForResources(theCount, txTemplate);
|
||||
retVal += doPerformReindexingPassForConcepts(txTemplate);
|
||||
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
|
||||
public TagList getAllTags(RequestDetails theRequestDetails) {
|
||||
// Notify interceptors
|
||||
|
|
|
@ -78,7 +78,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter) {
|
||||
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
ValueSet source = loadValueSetForExpansion(theId);
|
||||
return expand(source, theFilter);
|
||||
|
||||
|
@ -179,7 +179,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
}
|
||||
|
||||
@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;
|
||||
|
||||
boolean haveCodeableConcept = theCodeableConcept != null && theCodeableConcept.getCoding().size() > 0;
|
||||
|
@ -212,7 +212,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
}
|
||||
|
||||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null);
|
||||
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
|
@ -314,7 +314,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
|
||||
List<IIdType> valueSetIds = findCodeSystemIdsContainingSystemAndCode(code, system);
|
||||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null);
|
||||
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||
LookupCodeResult result = lookup(contains, system, code);
|
||||
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.IPrimitiveType;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -34,7 +36,7 @@ public interface IFhirResourceDaoValueSet<T extends IBaseResource, CD, CC> exten
|
|||
|
||||
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 {
|
||||
private String myDisplay;
|
||||
|
|
|
@ -26,6 +26,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
import java.nio.file.FileVisitOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
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.IFhirResourceDaoValueSet;
|
||||
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.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
|
@ -70,8 +72,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
private IFhirResourceDaoCodeSystem<CodeSystem, CodeableConcept, Coding> myCodeSystemDao;
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, String theFilter) {
|
||||
ValueSet source = myValidationSupport.fetchResource(getContext(), ValueSet.class, theId.getValue());
|
||||
public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theFilter);
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
||||
|
||||
ValueSet retVal = new ValueSet();
|
||||
retVal.getMeta().setLastUpdated(new Date());
|
||||
retVal.setExpansion(expansion);
|
||||
return retVal;
|
||||
}
|
||||
|
@ -166,7 +169,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
|
||||
@Override
|
||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
List<IIdType> valueSetIds = Collections.emptyList();
|
||||
List<IIdType> codeSystemIds = Collections.emptyList();
|
||||
|
@ -205,7 +208,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
}
|
||||
|
||||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null);
|
||||
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
|
@ -219,7 +222,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
}
|
||||
|
||||
for (IIdType nextId : codeSystemIds) {
|
||||
ValueSet expansion = expand(nextId, null);
|
||||
ValueSet expansion = expand(nextId, null, theRequestDetails);
|
||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||
if (result != null) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -39,6 +40,8 @@ import javax.persistence.Index;
|
|||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.PreUpdate;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
@ -49,45 +52,54 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
|||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
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.Analyzer;
|
||||
import org.hibernate.search.annotations.AnalyzerDef;
|
||||
import org.hibernate.search.annotations.AnalyzerDefs;
|
||||
import org.hibernate.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Fields;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
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.search.DeferConceptIndexingInterceptor;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Indexed()
|
||||
@Indexed(interceptor=DeferConceptIndexingInterceptor.class)
|
||||
@Table(name="TRM_CONCEPT", uniqueConstraints= {
|
||||
@UniqueConstraint(name="IDX_CONCEPT_CS_CODE", columnNames= {"CODESYSTEM_PID", "CODE"})
|
||||
}, indexes= {
|
||||
@Index(name = "IDX_CONCEPT_INDEXSTATUS", columnList="INDEX_STATUS")
|
||||
})
|
||||
@AnalyzerDefs({
|
||||
@AnalyzerDef(name = "conceptParentPidsAnalyzer",
|
||||
tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
|
||||
filters = {
|
||||
})
|
||||
})
|
||||
//@formatter:on
|
||||
public class TermConcept implements Serializable {
|
||||
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;
|
||||
|
||||
@OneToMany(fetch=FetchType.LAZY, mappedBy="myParent")
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade= {})
|
||||
private Collection<TermConceptParentChildLink> myChildren;
|
||||
|
||||
@Column(name="CODE", length=100, nullable=false)
|
||||
@Fields({
|
||||
@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),
|
||||
})
|
||||
@Column(name = "CODE", length = 100, nullable = false)
|
||||
@Fields({ @Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")), })
|
||||
private String myCode;
|
||||
|
||||
@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;
|
||||
|
||||
@Column(name="CODESYSTEM_PID", insertable=false, updatable=false)
|
||||
@Fields({
|
||||
@Field(name="myCodeSystemVersionPid")
|
||||
})
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||
@Fields({ @Field(name = "myCodeSystemVersionPid") })
|
||||
private long myCodeSystemVersionPid;
|
||||
|
||||
//@formatter:off
|
||||
|
@ -102,21 +114,19 @@ public class TermConcept implements Serializable {
|
|||
//@formatter:on
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name="SEQ_CONCEPT_PID", sequenceName="SEQ_CONCEPT_PID")
|
||||
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CONCEPT_PID")
|
||||
@Column(name="PID")
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@Column(name = "INDEX_STATUS", nullable = true)
|
||||
private Long myIndexStatus;
|
||||
|
||||
@Transient
|
||||
@Fields({
|
||||
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
||||
})
|
||||
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "conceptParentPidsAnalyzer"))
|
||||
private String myParentPids;
|
||||
|
||||
@OneToMany(cascade= {}, fetch=FetchType.LAZY, mappedBy="myChild")
|
||||
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myChild")
|
||||
private Collection<TermConceptParentChildLink> myParents;
|
||||
|
||||
public TermConcept() {
|
||||
|
@ -155,7 +165,7 @@ public class TermConcept implements Serializable {
|
|||
return true;
|
||||
}
|
||||
|
||||
TermConcept obj = (TermConcept)theObj;
|
||||
TermConcept obj = (TermConcept) theObj;
|
||||
|
||||
EqualsBuilder b = new EqualsBuilder();
|
||||
b.append(myCodeSystem, obj.myCodeSystem);
|
||||
|
@ -190,6 +200,10 @@ public class TermConcept implements Serializable {
|
|||
return myIndexStatus;
|
||||
}
|
||||
|
||||
public String getParentPidsAsString() {
|
||||
return myParentPids;
|
||||
}
|
||||
|
||||
public Collection<TermConceptParentChildLink> getParents() {
|
||||
if (myParents == null) {
|
||||
myParents = new ArrayList<TermConceptParentChildLink>();
|
||||
|
@ -205,6 +219,28 @@ public class TermConcept implements Serializable {
|
|||
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) {
|
||||
myCode = theCode;
|
||||
}
|
||||
|
@ -237,6 +273,10 @@ public class TermConcept implements Serializable {
|
|||
b.append(next);
|
||||
}
|
||||
|
||||
if (b.length() == 0) {
|
||||
b.append("NONE");
|
||||
}
|
||||
|
||||
myParentPids = b.toString();
|
||||
}
|
||||
|
||||
|
@ -244,5 +284,4 @@ public class TermConcept implements Serializable {
|
|||
public String toString() {
|
||||
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{
|
||||
// ********************************************
|
||||
// IF YOU ADD HERE MAKE SURE ORDER IS PRESERVED
|
||||
ISA
|
||||
}
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return myPid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
@IdParam(optional=true) IdDt theId,
|
||||
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
||||
@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
|
||||
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
|
@ -72,7 +73,7 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
if (haveId) {
|
||||
return dao.expand(theId, toFilterString(theFilter));
|
||||
return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
|
||||
} else if (haveIdentifier) {
|
||||
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
||||
} else {
|
||||
|
@ -155,14 +156,15 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
|
||||
@OperationParam(name="display", min=0, max=1) StringDt theDisplay,
|
||||
@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
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
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();
|
||||
retVal.addParameter().setName("result").setValue(new BooleanDt(result.isResult()));
|
||||
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.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDstu3<ValueSet> {
|
||||
|
@ -50,7 +51,8 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
|||
@IdParam(optional=true) IdType theId,
|
||||
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
||||
@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
|
||||
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
|
@ -69,7 +71,7 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
|||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
|
||||
if (haveId) {
|
||||
return dao.expand(theId, toFilterString(theFilter));
|
||||
return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
|
||||
} else if (haveIdentifier) {
|
||||
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
||||
} else {
|
||||
|
@ -118,14 +120,15 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
|
|||
@OperationParam(name="system", min=0, max=1) UriType theSystem,
|
||||
@OperationParam(name="display", min=0, max=1) StringType theDisplay,
|
||||
@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
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
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();
|
||||
retVal.addParameter().setName("result").setValue(new BooleanType(result.isResult()));
|
||||
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.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
|
@ -32,10 +33,17 @@ import javax.persistence.EntityManager;
|
|||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
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.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
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.TermConcept;
|
||||
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.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
@ -85,6 +95,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
protected EntityManager myEntityManager;
|
||||
|
||||
private boolean myProcessDeferred = true;
|
||||
private long myNextReindexPass;
|
||||
|
||||
private boolean addToSet(Set<TermConcept> theSetToPopulate, TermConcept theConcept) {
|
||||
boolean retVal = theSetToPopulate.add(theConcept);
|
||||
|
@ -209,15 +220,6 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
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) {
|
||||
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
||||
return;
|
||||
|
@ -231,12 +233,8 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
theConcept.setCodeSystem(theCodeSystem);
|
||||
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||
|
||||
Set<Long> parentPids = new HashSet<Long>();
|
||||
parentPids(theConcept, parentPids);
|
||||
theConcept.setParentPids(parentPids);
|
||||
|
||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||
myConceptDao.save(theConcept);
|
||||
saveConcept(theConcept);
|
||||
} else {
|
||||
myConceptsToSaveLater.add(theConcept);
|
||||
}
|
||||
|
@ -247,7 +245,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
|
||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
saveConceptLink(next);
|
||||
} else {
|
||||
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) {
|
||||
if (theNext.getCodeSystem() != null) {
|
||||
return;
|
||||
|
@ -270,17 +306,21 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
@Override
|
||||
public synchronized void saveDeferred() {
|
||||
if (!myProcessDeferred || ((myConceptsToSaveLater.isEmpty() && myConceptLinksToSaveLater.isEmpty()))) {
|
||||
return;
|
||||
processReindexing();
|
||||
}
|
||||
|
||||
int codeCount = 0, relCount = 0;
|
||||
StopWatch stopwatch = new StopWatch();
|
||||
|
||||
int count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptsToSaveLater.size());
|
||||
ourLog.info("Saving {} deferred concepts...", count);
|
||||
while (codeCount < count && myConceptsToSaveLater.size() > 0) {
|
||||
TermConcept next = myConceptsToSaveLater.remove(0);
|
||||
myConceptDao.save(next);
|
||||
codeCount++;
|
||||
codeCount += saveConcept(next);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -288,12 +328,54 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ourLog.info("Saving {} deferred concept relationships...", count);
|
||||
while (relCount < count && myConceptLinksToSaveLater.size() > 0) {
|
||||
TermConceptParentChildLink next = myConceptLinksToSaveLater.remove(0);
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
saveConceptLink(next);
|
||||
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
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryWrapperFilter;
|
||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||
import org.hibernate.search.jpa.FullTextQuery;
|
||||
import org.hibernate.search.query.dsl.BooleanJunction;
|
||||
|
@ -78,56 +79,38 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
@Autowired
|
||||
private ValueSetExpander myValueSetExpander;
|
||||
|
||||
@Override
|
||||
public List<VersionIndependentConcept> expandValueSet(String theValueSet) {
|
||||
ValueSet source = new ValueSet();
|
||||
source.getCompose().addImport(theValueSet);
|
||||
try {
|
||||
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);
|
||||
private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set<String> addedCodes, TermConcept nextConcept) {
|
||||
if (addedCodes.add(nextConcept.getCode())) {
|
||||
ValueSetExpansionContainsComponent contains = retVal.addContains();
|
||||
contains.setCode(nextConcept.getCode());
|
||||
contains.setSystem(system);
|
||||
contains.setDisplay(nextConcept.getDisplay());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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);
|
||||
private void addDisplayFilterExact(QueryBuilder qb, BooleanJunction<?> bool, ConceptSetFilterComponent nextFilter) {
|
||||
bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery());
|
||||
}
|
||||
|
||||
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
|
||||
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||
String system = theInclude.getSystem();
|
||||
ourLog.info("Starting expansion around code system: {}", system);
|
||||
|
||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(system);
|
||||
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());
|
||||
|
||||
for (ConceptSetFilterComponent nextFilter : theInclude.getFilter()) {
|
||||
if (nextFilter.getProperty().equals("display") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
if (isNotBlank(nextFilter.getValue())) {
|
||||
bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery());
|
||||
}
|
||||
} else if (nextFilter.getOp() == FilterOperator.ISA) {
|
||||
if (isNotBlank(nextFilter.getValue())) {
|
||||
if (isNotBlank(nextFilter.getValue())) {
|
||||
if (nextFilter.getProperty().equals("display:exact") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else if (nextFilter.getProperty().equals("display") && nextFilter.getOp() == FilterOperator.EQUAL) {
|
||||
if (nextFilter.getValue().trim().contains(" ")) {
|
||||
addDisplayFilterExact(qb, bool, nextFilter);
|
||||
} else {
|
||||
addDisplayFilterInexact(qb, bool, nextFilter);
|
||||
}
|
||||
} else if ((nextFilter.getProperty().equals("concept") || nextFilter.getProperty().equals("code")) && nextFilter.getOp() == FilterOperator.ISA) {
|
||||
TermConcept code = super.findCode(system, nextFilter.getValue());
|
||||
if (code == null) {
|
||||
throw new InvalidRequestException("Invalid filter criteria - code does not exist: {" + system + "}" + nextFilter.getValue());
|
||||
}
|
||||
|
||||
ourLog.info(" * Filtering on codes with a parent of {}/{}/{}", code.getId(), code.getCode(), code.getDisplay());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
||||
} else {
|
||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||
}
|
||||
} else {
|
||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
Query luceneQuery = bool.createQuery();
|
||||
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
||||
jpaQuery.setMaxResults(1000);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TermConcept> result = jpaQuery.getResultList();
|
||||
for (TermConcept nextConcept : result) {
|
||||
addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept);
|
||||
}
|
||||
|
||||
retVal.setTotal(jpaQuery.getResultSize());
|
||||
}
|
||||
|
||||
if (!haveIncludeCriteria) {
|
||||
|
@ -197,18 +193,28 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
}
|
||||
}
|
||||
|
||||
retVal.setTotal(retVal.getContains().size());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set<String> addedCodes, TermConcept nextConcept) {
|
||||
if (addedCodes.add(nextConcept.getCode())) {
|
||||
ValueSetExpansionContainsComponent contains = retVal.addContains();
|
||||
contains.setCode(nextConcept.getCode());
|
||||
contains.setSystem(system);
|
||||
contains.setDisplay(nextConcept.getDisplay());
|
||||
@Override
|
||||
public List<VersionIndependentConcept> expandValueSet(String theValueSet) {
|
||||
ValueSet source = new ValueSet();
|
||||
source.getCompose().addImport(theValueSet);
|
||||
try {
|
||||
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
|
||||
|
@ -238,6 +244,33 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
|||
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
|
||||
@Override
|
||||
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.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
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.CSVRecord;
|
||||
import org.apache.commons.csv.QuoteMode;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -102,6 +98,8 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
|||
}
|
||||
ourLog.info(b.toString(), theConcept.getCode());
|
||||
childIter.remove();
|
||||
nextChild.getParents().remove(next);
|
||||
|
||||
} else {
|
||||
dropCircularRefs(nextChild, theChain, theCode2concept, theCircularCounter);
|
||||
}
|
||||
|
|
|
@ -32,4 +32,14 @@ public class StopWatch {
|
|||
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.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
|
@ -25,7 +24,6 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
||||
|
@ -58,7 +56,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = 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());
|
||||
}
|
||||
|
||||
|
@ -71,7 +69,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = 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());
|
||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
||||
}
|
||||
|
@ -85,7 +83,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = 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());
|
||||
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");
|
||||
CodingDt coding = 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());
|
||||
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");
|
||||
CodingDt coding = 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());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -127,7 +125,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = null;
|
||||
CodeableConceptDt codeableConcept = new CodeableConceptDt("http://loinc.org", "11378-7");
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept);
|
||||
ValidateCodeResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
|
||||
assertTrue(result.isResult());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -141,7 +139,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
StringDt display = null;
|
||||
CodingDt coding = 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());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -150,7 +148,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
public void testExpandById() throws IOException {
|
||||
String resp;
|
||||
|
||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null);
|
||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
// @formatter:off
|
||||
|
@ -175,7 +173,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
* Filter with display name
|
||||
*/
|
||||
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
|
@ -188,7 +186,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
|
|||
* Filter with code
|
||||
*/
|
||||
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"));
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"), mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,6 @@ import org.junit.Test;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
||||
|
@ -62,7 +61,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
StringType display = null;
|
||||
Coding coding = 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());
|
||||
}
|
||||
|
||||
|
@ -75,7 +74,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
StringType display = null;
|
||||
Coding coding = 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());
|
||||
assertEquals("Systolic blood pressure--expiration", result.getDisplay());
|
||||
}
|
||||
|
@ -89,7 +88,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
StringType display = null;
|
||||
Coding coding = 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());
|
||||
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");
|
||||
Coding coding = 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());
|
||||
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");
|
||||
Coding coding = 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());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -132,7 +131,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
Coding coding = null;
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
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());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -146,7 +145,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
StringType display = null;
|
||||
Coding coding = 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());
|
||||
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
|
||||
}
|
||||
|
@ -155,7 +154,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
public void testExpandById() throws IOException {
|
||||
String resp;
|
||||
|
||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null);
|
||||
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
|
||||
|
@ -176,7 +175,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
|
|||
* Filter with display name
|
||||
*/
|
||||
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@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.UriDt;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test {
|
||||
|
@ -251,7 +250,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
|
|||
expanded = (ValueSet) respParam.getParameter().get(0).getResource();
|
||||
//@formatter:on
|
||||
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"));
|
||||
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
|
||||
ourLog.info(resp);
|
||||
//@formatter:off
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
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.containsStringIgnoringCase;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
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.CodeSystem;
|
||||
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.StringType;
|
||||
import org.hl7.fhir.dstu3.model.UriType;
|
||||
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.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
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.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3ValueSetTest.class);
|
||||
private IIdType myExtensionalVsId;
|
||||
private IIdType myLocalValueSetId;
|
||||
private ValueSet myLocalVs;
|
||||
|
||||
@AfterClass
|
||||
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
|
||||
public void testExpandByIdWithFilter() throws IOException {
|
||||
|
||||
|
@ -231,4 +376,102 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
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)
|
||||
@Test
|
||||
public void testSuggestKeywords() throws Exception {
|
||||
|
|
|
@ -30,10 +30,6 @@ public class TerminologyLoaderSvcIntegrationTest extends BaseJpaDstu3Test {
|
|||
@Test
|
||||
@Ignore
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
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.verify;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -25,6 +25,7 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.apache.commons.lang3.Validate;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
@ -79,6 +80,21 @@ public class TerminologyLoaderSvcTest {
|
|||
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
|
||||
public void testLoadSnomedCt() throws Exception {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
|
|
@ -17,3 +17,4 @@ id effectiveTime active moduleId definitionStatusId
|
|||
207527008 20020131 1 900000000000207008 900000000000074008
|
||||
207527008 20040731 1 900000000000207008 900000000000073002
|
||||
207527008 20090731 0 900000000000207008 900000000000074008
|
||||
404684003 20040131 1 900000000000207008 900000000000074008
|
||||
|
|
|
@ -67,6 +67,8 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
|
|||
ValueSetExpansionOutcome vso;
|
||||
try {
|
||||
vso = getExpander().expand(theSource);
|
||||
} catch (InvalidRequestException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
@ -125,7 +127,9 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
|
|||
|
||||
@Override
|
||||
public ValueSetExpander getExpander() {
|
||||
return new ValueSetExpanderSimple(this, this);
|
||||
ValueSetExpanderSimple retVal = new ValueSetExpanderSimple(this, this);
|
||||
retVal.setMaxExpansionSize(Integer.MAX_VALUE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -70,8 +70,10 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
private Set<String> excludeKeys = new HashSet<String>();
|
||||
private ValueSetExpanderFactory factory;
|
||||
private ValueSet focus;
|
||||
private int maxExpansionSize = 500;
|
||||
|
||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private int total;
|
||||
|
||||
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
||||
super();
|
||||
|
@ -79,6 +81,10 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
this.factory = factory;
|
||||
}
|
||||
|
||||
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
||||
maxExpansionSize = theMaxExpansionSize;
|
||||
}
|
||||
|
||||
private void addCode(String system, String code, String display) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(system);
|
||||
|
@ -101,7 +107,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
}
|
||||
|
||||
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()) + ")");
|
||||
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||
|
@ -111,6 +117,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
addCode(c.getSystem(), c.getCode(), c.getDisplay());
|
||||
}
|
||||
|
||||
total = expand.getTotal();
|
||||
}
|
||||
|
||||
private void excludeCode(String theSystem, String theCode) {
|
||||
|
@ -171,6 +179,11 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
focus.getExpansion().getContains().add(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (total > 0) {
|
||||
focus.getExpansion().setTotal(total);
|
||||
}
|
||||
|
||||
return new ValueSetExpansionOutcome(focus, null);
|
||||
} catch (RuntimeException e) {
|
||||
// TODO: we should put something more specific instead of just Exception below, since
|
||||
|
|
Loading…
Reference in New Issue