Allow terminology service to work without having Lucene enabled for
simple ValueSet expansions
This commit is contained in:
parent
10c348d44f
commit
485335e975
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.parser;
|
|||
* 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.
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jaxrs.server.util;
|
|||
* 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.
|
||||
|
|
|
@ -98,9 +98,9 @@ import static org.apache.commons.lang3.StringUtils.*;
|
|||
* 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.
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.term;
|
|||
* 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.
|
||||
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -480,6 +487,19 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
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();
|
||||
|
||||
|
@ -663,6 +683,20 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -8,9 +8,13 @@ import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
|
|||
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.*;
|
||||
|
@ -27,7 +31,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
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})
|
||||
|
@ -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
|
||||
|
@ -168,6 +182,42 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
|||
}
|
||||
}
|
||||
|
||||
@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() {
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.server;
|
|||
* 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.
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue