Skip to content

Commit

Permalink
Allow terminology service to work without having Lucene enabled for
Browse files Browse the repository at this point in the history
simple ValueSet expansions
  • Loading branch information
jamesagnew committed Feb 15, 2019
1 parent 10c348d commit 485335e
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -24,6 +24,7 @@
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
Expand Down Expand Up @@ -139,35 +140,41 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
private TransactionTemplate myTxTemplate;
@Autowired
private PlatformTransactionManager myTransactionManager;
@Autowired(required = false)
private IFulltextSearchSvc myFulltextSearchSvc;


/**
* @param theAdd If true, add the code. If false, remove the code.
* @param theCodeCounter
*/
private void addCodeIfNotAlreadyAdded(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, TermConcept theConcept, boolean theAdd, AtomicInteger theCodeCounter) {
String codeSystem = theConcept.getCodeSystemVersion().getCodeSystem().getCodeSystemUri();
String code = theConcept.getCode();
if (theAdd && theAddedCodes.add(code)) {
String codeSystem = theConcept.getCodeSystemVersion().getCodeSystem().getCodeSystemUri();
String display = theConcept.getDisplay();
Collection<TermConceptDesignation> designations = theConcept.getDesignations();
addCodeIfNotAlreadyAdded(theExpansionComponent, theAddedCodes, designations, theAdd, theCodeCounter, codeSystem, code, display);
}

private void addCodeIfNotAlreadyAdded(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, Collection<TermConceptDesignation> theDesignations, boolean theAdd, AtomicInteger theCodeCounter, String theCodeSystem, String theCode, String theDisplay) {
if (isNotBlank(theCode) && theAdd && theAddedCodes.add(theCode)) {
ValueSet.ValueSetExpansionContainsComponent contains = theExpansionComponent.addContains();
contains.setCode(code);
contains.setSystem(codeSystem);
contains.setDisplay(theConcept.getDisplay());
for (TermConceptDesignation nextDesignation : theConcept.getDesignations()) {
contains
.addDesignation()
.setValue(nextDesignation.getValue())
.getUse()
.setSystem(nextDesignation.getUseSystem())
.setCode(nextDesignation.getUseCode())
.setDisplay(nextDesignation.getUseDisplay());
contains.setCode(theCode);
contains.setSystem(theCodeSystem);
contains.setDisplay(theDisplay);
if (theDesignations != null) {
for (TermConceptDesignation nextDesignation : theDesignations) {
contains
.addDesignation()
.setValue(nextDesignation.getValue())
.getUse()
.setSystem(nextDesignation.getUseSystem())
.setCode(nextDesignation.getUseCode())
.setDisplay(nextDesignation.getUseDisplay());
}
}

theCodeCounter.incrementAndGet();
}

if (!theAdd && theAddedCodes.remove(code)) {
String codeSystem = theConcept.getCodeSystemVersion().getCodeSystem().getCodeSystemUri();
removeCodeFromExpansion(codeSystem, code, theExpansionComponent);
if (!theAdd && theAddedCodes.remove(theCode)) {
removeCodeFromExpansion(theCodeSystem, theCode, theExpansionComponent);
theCodeCounter.decrementAndGet();
}
}
Expand Down Expand Up @@ -480,6 +487,19 @@ public void expandValueSetHandleIncludeOrExclude(ValueSet.ValueSetExpansionCompo
if (cs != null) {
TermCodeSystemVersion csv = cs.getCurrentVersion();
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);

/*
* If FullText searching is not enabled, we can handle only basic expansions
* since we're going to do it without the database.
*/
if (myFulltextSearchSvc == null) {
expandWithoutHibernateSearch(theExpansionComponent, theAddedCodes, theInclude, system, theAdd, theCodeCounter);
return;
}

/*
* Ok, let's use hibernate search to build the expansion
*/
QueryBuilder qb = em.getSearchFactory().buildQueryBuilder().forEntity(TermConcept.class).get();
BooleanJunction<?> bool = qb.bool();

Expand Down Expand Up @@ -663,6 +683,20 @@ public void expandValueSetHandleIncludeOrExclude(ValueSet.ValueSetExpansionCompo
}
}

private void expandWithoutHibernateSearch(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) {
ourLog.trace("Hibernate search is not enabled");
Validate.isTrue(theExpansionComponent.getParameter().isEmpty(), "Can not exapnd ValueSet with parameters - Hibernate Search is not enabled on this server.");
Validate.isTrue(theInclude.getFilter().isEmpty(), "Can not expand ValueSet with filters - Hibernate Search is not enabled on this server.");
Validate.isTrue(isNotBlank(theSystem), "Can not expand ValueSet without explicit system - Hibernate Search is not enabled on this server.");

for (ValueSet.ConceptReferenceComponent next : theInclude.getConcept()) {
if (!theSystem.equals(theInclude.getSystem())) {
continue;
}
addCodeIfNotAlreadyAdded(theExpansionComponent, theAddedCodes, null, theAdd, theCodeCounter, theSystem, next.getCode(), next.getDisplay());
}
}

private void fetchChildren(TermConcept theConcept, Set<TermConcept> theSetToPopulate) {
for (TermConceptParentChildLink nextChildLink : theConcept.getChildren()) {
TermConcept nextChild = nextChildLink.getChild();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.model.*;
Expand All @@ -27,7 +31,11 @@

import javax.persistence.EntityManager;

import java.util.List;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestR4WithoutLuceneConfig.class})
Expand Down Expand Up @@ -62,6 +70,12 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
@Qualifier("myCodeSystemDaoR4")
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
@Autowired
@Qualifier("myValueSetDaoR4")
private IFhirResourceDao<ValueSet> myValueSetDao;
@Autowired
@Qualifier("myObservationDaoR4")
private IFhirResourceDao<Observation> myObservationDao;
@Autowired
@Qualifier("myCompartmentDefinitionDaoR4")
private IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao;
@Autowired
Expand Down Expand Up @@ -168,6 +182,42 @@ public void testSearchWithText() {
}
}

@Test
public void testSearchByCodeIn() {
CodeSystem cs = new CodeSystem();
cs.setUrl("http://fooCS");
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.addConcept().setCode("CODEA");
cs.addConcept().setCode("CODEB");
myCodeSystemDao.create(cs);

ValueSet vs = new ValueSet();
vs.setUrl("http://fooVS");
vs.getCompose()
.addInclude()
.setSystem("http://fooCS")
.addConcept(new ValueSet.ConceptReferenceComponent().setCode("CODEA"));
myValueSetDao.create(vs);

Observation obs = new Observation();
obs.getCode().addCoding().setSystem("http://fooCS").setCode("CODEA");
String obs1id = myObservationDao.create(obs).getId().toUnqualifiedVersionless().getValue();

obs = new Observation();
obs.getCode().addCoding().setSystem("http://fooCS").setCode("CODEB");
myObservationDao.create(obs).getId().toUnqualifiedVersionless().getValue();

SearchParameterMap map = new SearchParameterMap();
map.setLoadSynchronous(true);
map.add("code", new TokenParam("http://fooVS").setModifier(TokenParamModifier.IN));
IBundleProvider results = myObservationDao.search(map);
List<IBaseResource> resultsList = results.getResources(0, 10);
assertEquals(1, resultsList.size());
assertEquals(obs1id, resultsList.get(0).getIdElement().toUnqualifiedVersionless().getValue());

}



@AfterClass
public static void afterClassClearContext() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
5 changes: 5 additions & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
requesting extensions to be included caused the extensions to be included but
not any values contained within. This has been corrected.
</action>
<action type="add">
The JPA terminology service can now detect when Hibvernate Search (Lucene)
is not enabled, and will perform simple ValueSet expansions without relying
on Hibenrate Search in such cases.
</action>
</release>
<release version="3.7.0" date="2019-02-06" description="Gale">
<action type="add">
Expand Down

0 comments on commit 485335e

Please sign in to comment.