More cleanup and test fixes.

This commit is contained in:
ianmarshall 2020-04-24 16:23:59 -04:00
parent 197bf2b6a8
commit 0e45db0ba9
27 changed files with 100 additions and 811 deletions

View File

@ -72,8 +72,6 @@ public class RunServerCommand extends BaseCommand {
options.addOption(null, OPTION_DISABLE_REFERENTIAL_INTEGRITY, false, "If this flag is set, the server will not enforce referential integrity");
addOptionalOption(options, "u", "url", "Url", "If this option is set, specifies the JDBC URL to use for the database connection");
addOptionalOption(options, "d", "default-size", "PageSize", "If this option is set, specifies the default page size for number of query results");
addOptionalOption(options, "m", "max-size", "MaxSize", "If this option is set, specifies the maximum result set size for queries");
Long defaultReuseSearchResults = DaoConfig.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
String defaultReuseSearchResultsStr = defaultReuseSearchResults == null ? "off" : String.valueOf(defaultReuseSearchResults);
@ -112,17 +110,6 @@ public class RunServerCommand extends BaseCommand {
ContextHolder.setDatabaseUrl(theCommandLine.getOptionValue("u"));
String defaultPageSize = theCommandLine.getOptionValue("d");
String maxPageSize = theCommandLine.getOptionValue("m");
if (defaultPageSize != null) {
ContextHolder.setDefaultPageSize(Integer.valueOf(defaultPageSize));
if (maxPageSize != null) {
ContextHolder.setMaxPageSize(Integer.valueOf(maxPageSize));
} else {
ContextHolder.setMaxPageSize(Integer.valueOf(defaultPageSize));
}
}
String reuseSearchResults = theCommandLine.getOptionValue(OPTION_REUSE_SEARCH_RESULTS_MILLIS);
if (reuseSearchResults != null) {
if (reuseSearchResults.equals("off")) {

View File

@ -136,10 +136,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -33,8 +33,6 @@ public class ContextHolder {
private static String ourPath;
private static Long ourReuseSearchResultsMillis;
private static String ourDatabaseUrl;
private static Integer myDefaultPageSize = 10;
private static Integer myMaxPageSize = 50;
static {
ourReuseSearchResultsMillis = DaoConfig.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
@ -102,21 +100,4 @@ public class ContextHolder {
public static void setDatabaseUrl(String theDatabaseUrl) {
ourDatabaseUrl = theDatabaseUrl;
}
public static void setDefaultPageSize(Integer theDefaultPageSize) {
myDefaultPageSize = theDefaultPageSize;
}
public static Integer getDefaultPageSize() {
return myDefaultPageSize;
}
public static void setMaxPageSize(Integer theMaxPageSize) {
myMaxPageSize = theMaxPageSize;
}
public static Integer getMaxPageSize() {
return myMaxPageSize;
}
}

View File

@ -160,7 +160,7 @@ public class JpaServerDemo extends RestfulServer {
/*
* This is a simple paging strategy that keeps the last 10 searches in memory
*/
setPagingProvider(new FifoMemoryPagingProvider(10).setDefaultPageSize(ContextHolder.getDefaultPageSize()).setMaximumPageSize(ContextHolder.getMaxPageSize()));
setPagingProvider(new FifoMemoryPagingProvider(10));
// Register a CORS filter
CorsInterceptor corsInterceptor = new CorsInterceptor();

View File

@ -640,6 +640,28 @@
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<runOrder>alphabetical</runOrder>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate54-ddl-maven-plugin</artifactId>

View File

@ -8,9 +8,7 @@ import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.dstu3.TransactionProcessorVersionAdapterDstu3;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistDstu3Svc;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu3;

View File

@ -7,8 +7,6 @@ import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistSvc;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistR4Svc;
import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;

View File

@ -7,10 +7,8 @@ import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistR5Svc;
import ca.uhn.fhir.jpa.dao.r5.TransactionProcessorVersionAdapterR5;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR5;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcR5;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR5;

View File

@ -320,86 +320,30 @@ public class SearchBuilder implements ISearchBuilder {
}
/*
* Fulltext search
*/
/*
if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT)) {
if (myFulltextSearchSvc == null) {
if (myParams.containsKey(Constants.PARAM_TEXT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
} else if (myParams.containsKey(Constants.PARAM_CONTENT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT);
}
}
List<ResourcePersistentId> pids;
if (myParams.getEverythingMode() != null) {
pids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest);
} else {
pids = myFulltextSearchSvc.search(myResourceName, myParams);
}
if (pids.isEmpty()) {
// Will never match
pids = Collections.singletonList(new ResourcePersistentId(-1L));
}
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
} else if (myParams.isLastN()) {
if (myIElasticsearchSvc == null) {
if (myParams.isLastN()) {
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
}
}
if (myParams.isLastN()) {
Integer myMaxObservationsPerCode = null;
String[] maxCountParams = theRequest.getParameters().get("max");
if (maxCountParams != null && maxCountParams.length > 0) {
myMaxObservationsPerCode = Integer.valueOf(maxCountParams[0]);
} else {
throw new InvalidRequestException("Max parameter is required for $lastn operation");
}
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myMaxObservationsPerCode);
for (String lastnResourceId : lastnResourceIds) {
lastnPids.add(myIdHelperService.resolveResourcePersistentIds(myResourceName, lastnResourceId));
}
if (lastnPids.isEmpty()) {
// Will never match
pids = Collections.singletonList(new ResourcePersistentId(-1L));
}
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
}
}
*/
/*
* lastn search
* Fulltext or lastn search
*/
if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT) || myParams.isLastN()) {
List<ResourcePersistentId> lastnPids = new ArrayList<>();
List<ResourcePersistentId> fullTextSearchPids = new ArrayList<>();
if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT)) {
if (myFulltextSearchSvc == null) {
if (myParams.containsKey(Constants.PARAM_TEXT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
} else if (myParams.containsKey(Constants.PARAM_CONTENT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT);
List<ResourcePersistentId> pids = new ArrayList<>();
if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT)) {
if (myFulltextSearchSvc == null) {
if (myParams.containsKey(Constants.PARAM_TEXT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
} else if (myParams.containsKey(Constants.PARAM_CONTENT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT);
}
}
}
if (myParams.getEverythingMode() != null) {
fullTextSearchPids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest);
} else {
fullTextSearchPids = myFulltextSearchSvc.search(myResourceName, myParams);
}
} else {
if (myIElasticsearchSvc == null) {
if (myParams.isLastN()) {
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
if (myParams.getEverythingMode() != null) {
pids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest);
} else {
pids = myFulltextSearchSvc.search(myResourceName, myParams);
}
} else if (myParams.isLastN()) {
if (myIElasticsearchSvc == null) {
if (myParams.isLastN()) {
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
}
}
}
if (myParams.isLastN()) {
Integer myMaxObservationsPerCode = null;
String[] maxCountParams = theRequest.getParameters().get("max");
if (maxCountParams != null && maxCountParams.length > 0) {
@ -409,31 +353,16 @@ public class SearchBuilder implements ISearchBuilder {
}
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myMaxObservationsPerCode);
for (String lastnResourceId : lastnResourceIds) {
lastnPids.add(myIdHelperService.resolveResourcePersistentIds(myResourceName, lastnResourceId));
pids.add(myIdHelperService.resolveResourcePersistentIds(myResourceName, lastnResourceId));
}
}
}
//
List<ResourcePersistentId> pids;
if (fullTextSearchPids.isEmpty()) {
pids = lastnPids;
} else if (lastnPids.isEmpty()) {
pids = fullTextSearchPids;
} else {
// Intersection of the fullTextSearchPids and lastnPids
Set<ResourcePersistentId> pidIntersection = fullTextSearchPids.stream()
.distinct()
.filter(lastnPids::contains)
.collect(Collectors.toSet());
pids = new ArrayList<>(pidIntersection);
}
if (pids.isEmpty()) {
// Will never match
pids = Collections.singletonList(new ResourcePersistentId(-1L));
}
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
}
/*

View File

@ -1,132 +0,0 @@
package ca.uhn.fhir.jpa.dao.lastn;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedCodeCodingSearchParamDao;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedSearchParamLastNDao;
import ca.uhn.fhir.jpa.dao.lastn.entity.*;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.r4.model.DateTimeType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.*;
@Transactional(propagation = Propagation.REQUIRED)
public class ObservationLastNIndexPersistDstu3Svc {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
@Autowired
IObservationIndexedSearchParamLastNDao myResourceIndexedObservationLastNDao;
@Autowired
IObservationIndexedCodeCodingSearchParamDao myObservationIndexedCodeCodingSearchParamDao;
public void indexObservation(Observation theObservation) {
// Only index for lastn if Observation has a subject and effective date/time
if(theObservation.getSubject() == null || !theObservation.hasEffective()) {
return;
}
// Determine most recent effective date/time
Date effectiveDtm = null;
if (theObservation.hasEffectiveDateTimeType()) {
effectiveDtm = theObservation.getEffectiveDateTimeType().getValue();
} else if (theObservation.hasEffectivePeriod()) {
effectiveDtm = theObservation.getEffectivePeriod().getEnd();
}
if (effectiveDtm == null) {
return;
}
// Determine if an index already exists for Observation:
boolean observationIndexUpdate = false;
ObservationIndexedSearchParamLastNEntity indexedObservation = null;
if (theObservation.hasId()) {
indexedObservation = myResourceIndexedObservationLastNDao.findForIdentifier(theObservation.getIdElement().getIdPart());
}
if (indexedObservation == null) {
indexedObservation = new ObservationIndexedSearchParamLastNEntity();
} else {
observationIndexUpdate = true;
}
indexedObservation.setEffectiveDtm(effectiveDtm);
Reference subjectReference = theObservation.getSubject();
String subjectId = subjectReference.getReference();
String resourcePID = theObservation.getIdElement().getIdPart();
indexedObservation.setIdentifier(resourcePID);
indexedObservation.setSubject(subjectId);
// Build CodeableConcept entities for Observation.Category
Set<ObservationIndexedCategoryCodeableConceptEntity> categoryConcepts = new HashSet<>();
for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) {
// Build Coding entities for each category CodeableConcept
Set<ObservationIndexedCategoryCodingEntity> categoryCodingEntities = new HashSet<>();
ObservationIndexedCategoryCodeableConceptEntity categoryCodeableConceptEntity = new ObservationIndexedCategoryCodeableConceptEntity(categoryCodeableConcept.getText());
for(Coding categoryCoding : categoryCodeableConcept.getCoding()){
categoryCodingEntities.add(new ObservationIndexedCategoryCodingEntity(categoryCoding.getSystem(), categoryCoding.getCode(), categoryCoding.getDisplay()));
}
categoryCodeableConceptEntity.setObservationIndexedCategoryCodingEntitySet(categoryCodingEntities);
categoryConcepts.add(categoryCodeableConceptEntity);
}
indexedObservation.setCategoryCodeableConcepts(categoryConcepts);
// Build CodeableConcept entity for Observation.Code.
CodeableConcept codeCodeableConcept = theObservation.getCode();
String observationCodeNormalizedId = null;
// Determine if a Normalized ID was created previously for Observation Code
boolean observationCodeUpdate = false;
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
if (codeCoding.hasCode() && codeCoding.hasSystem()) {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForCodeAndSystem(codeCoding.getCode(), codeCoding.getSystem());
} else {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForDisplay(codeCoding.getDisplay());
}
if(observationCodeNormalizedId != null) {
observationCodeUpdate = true;
break;
}
}
// Generate a new a normalized ID if necessary
if (observationCodeNormalizedId == null) {
observationCodeNormalizedId = UUID.randomUUID().toString();
}
// Create/update normalized Observation Code index record
ObservationIndexedCodeCodeableConceptEntity codeableConceptField = new ObservationIndexedCodeCodeableConceptEntity(codeCodeableConcept.getText(), observationCodeNormalizedId);
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
codeableConceptField.addCoding(new ObservationIndexedCodeCodingEntity(codeCoding.getSystem(), codeCoding.getCode(), codeCoding.getDisplay(), observationCodeNormalizedId));
}
if (observationCodeUpdate) {
myEntityManager.merge(codeableConceptField);
} else {
myEntityManager.persist(codeableConceptField);
}
indexedObservation.setObservationCode(codeableConceptField);
indexedObservation.setCodeNormalizedId(observationCodeNormalizedId);
if (observationIndexUpdate) {
myEntityManager.merge(indexedObservation);
} else {
myEntityManager.persist(indexedObservation);
}
}
public void deleteObservationIndex(IBasePersistedResource theEntity) {
ObservationIndexedSearchParamLastNEntity deletedObservationLastNEntity = myResourceIndexedObservationLastNDao.findForIdentifier(theEntity.getIdDt().getIdPart());
if (deletedObservationLastNEntity != null) {
myEntityManager.remove(deletedObservationLastNEntity);
}
}
}

View File

@ -1,142 +0,0 @@
package ca.uhn.fhir.jpa.dao.lastn;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedCodeCodeableConceptSearchParamDao;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedCodeCodingSearchParamDao;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedSearchParamLastNDao;
import ca.uhn.fhir.jpa.dao.lastn.entity.*;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
import org.hl7.fhir.r4.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.*;
@Transactional(propagation = Propagation.REQUIRED)
public class ObservationLastNIndexPersistR4Svc {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
@Autowired
IObservationIndexedSearchParamLastNDao myResourceIndexedObservationLastNDao;
@Autowired
IObservationIndexedCodeCodingSearchParamDao myObservationIndexedCodeCodingSearchParamDao;
public void indexObservation(Observation theObservation) {
// Only index for lastn if Observation has a subject and effective date/time
if(theObservation.getSubject() == null || !theObservation.hasEffective()) {
return;
}
// Determine most recent effective date/time
Date effectiveDtm = null;
if (theObservation.hasEffectiveDateTimeType()) {
effectiveDtm = theObservation.getEffectiveDateTimeType().getValue();
} else if (theObservation.hasEffectiveInstantType()) {
effectiveDtm = theObservation.getEffectiveInstantType().getValue();
} else if (theObservation.hasEffectivePeriod()) {
effectiveDtm = theObservation.getEffectivePeriod().getEnd();
} else if (theObservation.hasEffectiveTiming()) {
List<DateTimeType> events = theObservation.getEffectiveTiming().getEvent();
for (DateTimeType event : events) {
Date eventDtm = event.getValue();
if (effectiveDtm == null || eventDtm.after(effectiveDtm)) {
effectiveDtm = eventDtm;
}
}
}
if (effectiveDtm == null) {
return;
}
// Determine if an index already exists for Observation:
boolean observationIndexUpdate = false;
ObservationIndexedSearchParamLastNEntity indexedObservation = null;
if (theObservation.hasId()) {
indexedObservation = myResourceIndexedObservationLastNDao.findForIdentifier(theObservation.getIdElement().getIdPart());
}
if (indexedObservation == null) {
indexedObservation = new ObservationIndexedSearchParamLastNEntity();
} else {
observationIndexUpdate = true;
}
indexedObservation.setEffectiveDtm(effectiveDtm);
Reference subjectReference = theObservation.getSubject();
String subjectId = subjectReference.getReference();
String resourcePID = theObservation.getIdElement().getIdPart();
indexedObservation.setIdentifier(resourcePID);
indexedObservation.setSubject(subjectId);
// Build CodeableConcept entities for Observation.Category
Set<ObservationIndexedCategoryCodeableConceptEntity> categoryConcepts = new HashSet<>();
for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) {
// Build Coding entities for each category CodeableConcept
Set<ObservationIndexedCategoryCodingEntity> categoryCodingEntities = new HashSet<>();
ObservationIndexedCategoryCodeableConceptEntity categoryCodeableConceptEntity = new ObservationIndexedCategoryCodeableConceptEntity(categoryCodeableConcept.getText());
for(Coding categoryCoding : categoryCodeableConcept.getCoding()){
categoryCodingEntities.add(new ObservationIndexedCategoryCodingEntity(categoryCoding.getSystem(), categoryCoding.getCode(), categoryCoding.getDisplay()));
}
categoryCodeableConceptEntity.setObservationIndexedCategoryCodingEntitySet(categoryCodingEntities);
categoryConcepts.add(categoryCodeableConceptEntity);
}
indexedObservation.setCategoryCodeableConcepts(categoryConcepts);
// Build CodeableConcept entity for Observation.Code.
CodeableConcept codeCodeableConcept = theObservation.getCode();
String observationCodeNormalizedId = null;
// Determine if a Normalized ID was created previously for Observation Code
boolean observationCodeUpdate = false;
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
if (codeCoding.hasCode() && codeCoding.hasSystem()) {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForCodeAndSystem(codeCoding.getCode(), codeCoding.getSystem());
} else {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForDisplay(codeCoding.getDisplay());
}
if(observationCodeNormalizedId != null) {
observationCodeUpdate = true;
break;
}
}
// Generate a new a normalized ID if necessary
if (observationCodeNormalizedId == null) {
observationCodeNormalizedId = UUID.randomUUID().toString();
}
// Create/update normalized Observation Code index record
ObservationIndexedCodeCodeableConceptEntity codeableConceptField = new ObservationIndexedCodeCodeableConceptEntity(codeCodeableConcept.getText(), observationCodeNormalizedId);
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
codeableConceptField.addCoding(new ObservationIndexedCodeCodingEntity(codeCoding.getSystem(), codeCoding.getCode(), codeCoding.getDisplay(), observationCodeNormalizedId));
}
if (observationCodeUpdate) {
myEntityManager.merge(codeableConceptField);
} else {
myEntityManager.persist(codeableConceptField);
}
indexedObservation.setObservationCode(codeableConceptField);
indexedObservation.setCodeNormalizedId(observationCodeNormalizedId);
if (observationIndexUpdate) {
myEntityManager.merge(indexedObservation);
} else {
myEntityManager.persist(indexedObservation);
}
}
public void deleteObservationIndex(IBasePersistedResource theEntity) {
ObservationIndexedSearchParamLastNEntity deletedObservationLastNEntity = myResourceIndexedObservationLastNDao.findForIdentifier(theEntity.getIdDt().getIdPart());
if(deletedObservationLastNEntity != null) {
myEntityManager.remove(deletedObservationLastNEntity);
}
}
}

View File

@ -1,142 +0,0 @@
package ca.uhn.fhir.jpa.dao.lastn;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedCodeCodingSearchParamDao;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedSearchParamLastNDao;
import ca.uhn.fhir.jpa.dao.lastn.entity.*;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Observation;
import org.hl7.fhir.r5.model.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.*;
@Transactional(propagation = Propagation.REQUIRED)
public class ObservationLastNIndexPersistR5Svc {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
@Autowired
IObservationIndexedSearchParamLastNDao myResourceIndexedObservationLastNDao;
@Autowired
IObservationIndexedCodeCodingSearchParamDao myObservationIndexedCodeCodingSearchParamDao;
public void indexObservation(Observation theObservation) {
// Only index for lastn if Observation has a subject and effective date/time
if(theObservation.getSubject() == null || !theObservation.hasEffective()) {
return;
}
// Determine most recent effective date/time
Date effectiveDtm = null;
if (theObservation.hasEffectiveDateTimeType()) {
effectiveDtm = theObservation.getEffectiveDateTimeType().getValue();
} else if (theObservation.hasEffectiveInstantType()) {
effectiveDtm = theObservation.getEffectiveInstantType().getValue();
} else if (theObservation.hasEffectivePeriod()) {
effectiveDtm = theObservation.getEffectivePeriod().getEnd();
} else if (theObservation.hasEffectiveTiming()) {
List<DateTimeType> events = theObservation.getEffectiveTiming().getEvent();
for (DateTimeType event : events) {
Date eventDtm = event.getValue();
if (effectiveDtm == null || eventDtm.after(effectiveDtm)) {
effectiveDtm = eventDtm;
}
}
}
if (effectiveDtm == null) {
return;
}
// Determine if an index already exists for Observation:
boolean observationIndexUpdate = false;
ObservationIndexedSearchParamLastNEntity indexedObservation = null;
if (theObservation.hasId()) {
indexedObservation = myResourceIndexedObservationLastNDao.findForIdentifier(theObservation.getIdElement().getIdPart());
}
if (indexedObservation == null) {
indexedObservation = new ObservationIndexedSearchParamLastNEntity();
} else {
observationIndexUpdate = true;
}
indexedObservation.setEffectiveDtm(effectiveDtm);
Reference subjectReference = theObservation.getSubject();
String subjectId = subjectReference.getReference();
String resourcePID = theObservation.getIdElement().getIdPart();
indexedObservation.setIdentifier(resourcePID);
indexedObservation.setSubject(subjectId);
// Build CodeableConcept entities for Observation.Category
Set<ObservationIndexedCategoryCodeableConceptEntity> categoryConcepts = new HashSet<>();
for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) {
// Build Coding entities for each category CodeableConcept
Set<ObservationIndexedCategoryCodingEntity> categoryCodingEntities = new HashSet<>();
ObservationIndexedCategoryCodeableConceptEntity categoryCodeableConceptEntity = new ObservationIndexedCategoryCodeableConceptEntity(categoryCodeableConcept.getText());
for(Coding categoryCoding : categoryCodeableConcept.getCoding()){
categoryCodingEntities.add(new ObservationIndexedCategoryCodingEntity(categoryCoding.getSystem(), categoryCoding.getCode(), categoryCoding.getDisplay()));
}
categoryCodeableConceptEntity.setObservationIndexedCategoryCodingEntitySet(categoryCodingEntities);
categoryConcepts.add(categoryCodeableConceptEntity);
}
indexedObservation.setCategoryCodeableConcepts(categoryConcepts);
// Build CodeableConcept entity for Observation.Code.
CodeableConcept codeCodeableConcept = theObservation.getCode();
String observationCodeNormalizedId = null;
// Determine if a Normalized ID was created previously for Observation Code
boolean observationCodeUpdate = false;
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
if (codeCoding.hasCode() && codeCoding.hasSystem()) {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForCodeAndSystem(codeCoding.getCode(), codeCoding.getSystem());
} else {
observationCodeNormalizedId = myObservationIndexedCodeCodingSearchParamDao.findForDisplay(codeCoding.getDisplay());
}
if(observationCodeNormalizedId != null) {
observationCodeUpdate = true;
break;
}
}
// Generate a new a normalized ID if necessary
if (observationCodeNormalizedId == null) {
observationCodeNormalizedId = UUID.randomUUID().toString();
}
// Create/update normalized Observation Code index record
ObservationIndexedCodeCodeableConceptEntity codeableConceptField = new ObservationIndexedCodeCodeableConceptEntity(codeCodeableConcept.getText(), observationCodeNormalizedId);
for (Coding codeCoding : codeCodeableConcept.getCoding()) {
codeableConceptField.addCoding(new ObservationIndexedCodeCodingEntity(codeCoding.getSystem(), codeCoding.getCode(), codeCoding.getDisplay(), observationCodeNormalizedId));
}
if (observationCodeUpdate) {
myEntityManager.merge(codeableConceptField);
} else {
myEntityManager.persist(codeableConceptField);
}
indexedObservation.setObservationCode(codeableConceptField);
indexedObservation.setCodeNormalizedId(observationCodeNormalizedId);
if (observationIndexUpdate) {
myEntityManager.merge(indexedObservation);
} else {
myEntityManager.persist(indexedObservation);
}
}
public void deleteObservationIndex(IBasePersistedResource theEntity) {
ObservationIndexedSearchParamLastNEntity deletedObservationLastNEntity = myResourceIndexedObservationLastNDao.findForIdentifier(theEntity.getIdDt().getIdPart());
if(deletedObservationLastNEntity != null) {
myEntityManager.remove(deletedObservationLastNEntity);
}
}
}

View File

@ -53,8 +53,12 @@ public class ObservationLastNIndexPersistSvc {
effectiveDtm = mySearchParameterExtractor.extractDateFromResource(effectiveDateElement.get(0), "Observation.effective");
}
// Only index for lastn if Observation has a subject and effective date/time
if (subjectId == null || effectiveDtm == null) {
// Build CodeableConcept entity for Observation.Code.
List<IBase> observationCodeCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.code", theResource);
// Only index for lastn if Observation has a subject, effective date/time and code
if (subjectId == null || effectiveDtm == null || observationCodeCodeableConcepts.size() == 0) {
return;
}
@ -76,17 +80,6 @@ public class ObservationLastNIndexPersistSvc {
indexedObservation.setIdentifier(resourcePID);
indexedObservation.setSubject(subjectId);
// Build CodeableConcept entities for Observation.Category
List<IBase> observationCategoryCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.category", theResource);
Set<ObservationIndexedCategoryCodeableConceptEntity> categoryCodeableConceptEntities = new HashSet<>();
for (IBase categoryCodeableConcept : observationCategoryCodeableConcepts) {
// Build CodeableConcept entities for each category CodeableConcept
categoryCodeableConceptEntities.add(getCategoryCodeableConceptEntities(categoryCodeableConcept));
}
indexedObservation.setCategoryCodeableConcepts(categoryCodeableConceptEntities);
// Build CodeableConcept entity for Observation.Code.
List<IBase> observationCodeCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.code", theResource);
// Determine if a Normalized ID was created previously for Observation Code
boolean observationCodeUpdate = false;
@ -102,6 +95,15 @@ public class ObservationLastNIndexPersistSvc {
// Create/update normalized Observation Code index record
ObservationIndexedCodeCodeableConceptEntity codeableConceptField = getCodeCodeableConcept(observationCodeCodeableConcepts.get(0), observationCodeNormalizedId);
// Build CodeableConcept entities for Observation.Category
List<IBase> observationCategoryCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.category", theResource);
Set<ObservationIndexedCategoryCodeableConceptEntity> categoryCodeableConceptEntities = new HashSet<>();
for (IBase categoryCodeableConcept : observationCategoryCodeableConcepts) {
// Build CodeableConcept entities for each category CodeableConcept
categoryCodeableConceptEntities.add(getCategoryCodeableConceptEntities(categoryCodeableConcept));
}
indexedObservation.setCategoryCodeableConcepts(categoryCodeableConceptEntities);
if (observationCodeUpdate) {
myEntityManager.merge(codeableConceptField);
} else {
@ -152,16 +154,18 @@ public class ObservationLastNIndexPersistSvc {
ResourceIndexedSearchParamToken param = mySearchParameterExtractor.createSearchParamForCoding("Observation",
new RuntimeSearchParam(null, null, "code", null, null, null, null, null, null, null),
nextCoding);
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(nextCoding);
if (code != null && system != null) {
codeCodeableConceptId = myObservationIndexedCodeCodingSearchParamDao.findForCodeAndSystem(code, system);
} else {
codeCodeableConceptId = myObservationIndexedCodeCodingSearchParamDao.findForDisplay(text);
}
if (codeCodeableConceptId != null) {
break;
if (param != null) {
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(nextCoding);
if (code != null && system != null) {
codeCodeableConceptId = myObservationIndexedCodeCodingSearchParamDao.findForCodeAndSystem(code, system);
} else {
codeCodeableConceptId = myObservationIndexedCodeCodingSearchParamDao.findForDisplay(text);
}
if (codeCodeableConceptId != null) {
break;
}
}
}
@ -172,20 +176,28 @@ public class ObservationLastNIndexPersistSvc {
ResourceIndexedSearchParamToken param = mySearchParameterExtractor.createSearchParamForCoding("Observation",
new RuntimeSearchParam(null, null, "category", null, null, null, null, null, null, null),
theValue);
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(theValue);
return new ObservationIndexedCategoryCodingEntity(system, code, text);
ObservationIndexedCategoryCodingEntity observationIndexedCategoryCodingEntity = null;
if (param != null) {
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(theValue);
observationIndexedCategoryCodingEntity = new ObservationIndexedCategoryCodingEntity(system, code, text);
}
return observationIndexedCategoryCodingEntity;
}
private ObservationIndexedCodeCodingEntity getCodeCoding(IBase theValue, String observationCodeNormalizedId) {
ResourceIndexedSearchParamToken param = mySearchParameterExtractor.createSearchParamForCoding("Observation",
new RuntimeSearchParam(null, null, "code", null, null, null, null, null, null, null),
theValue);
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(theValue);
return new ObservationIndexedCodeCodingEntity(system, code, text, observationCodeNormalizedId);
ObservationIndexedCodeCodingEntity observationIndexedCodeCodingEntity = null;
if (param != null) {
String system = param.getSystem();
String code = param.getValue();
String text = mySearchParameterExtractor.getDisplayTextForCoding(theValue);
observationIndexedCodeCodingEntity = new ObservationIndexedCodeCodingEntity(system, code, text, observationCodeNormalizedId);
}
return observationIndexedCodeCodingEntity;
}
public void deleteObservationIndex(IBasePersistedResource theEntity) {

View File

@ -22,6 +22,7 @@ public class ObservationIndexedCodeCodeableConceptEntity {
@Column(name = "CODEABLE_CONCEPT_TEXT", nullable = true)
private String myCodeableConceptText;
// TODO: Make coding a Collection. Need to first figure out how to maintain this over time.
@IndexedEmbedded(depth=2, prefix = "coding")
// @OneToMany(mappedBy = "myCodeableConceptId", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "CODEABLE_CONCEPT_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CONCEPT_CODE"))

View File

@ -21,14 +21,10 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDaoObservation;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedCodeCodingSearchParamDao;
import ca.uhn.fhir.jpa.dao.data.IObservationIndexedSearchParamLastNDao;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistSvc;
import ca.uhn.fhir.jpa.dao.lastn.ObservationLastNIndexPersistR4Svc;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.IBundleProvider;

View File

@ -1,153 +0,0 @@
package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoObservation;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import java.util.Set;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class BaseJpaResourceProviderObservationDstu2 extends JpaResourceProviderDstu2<Observation> {
/**
* Observation/$lastn
*/
@Operation(name = JpaConstants.OPERATION_LASTN, idempotent = true, bundleType = BundleTypeEnum.SEARCHSET)
public IBundleProvider observationLastN(
javax.servlet.http.HttpServletRequest theServletRequest,
javax.servlet.http.HttpServletResponse theServletResponse,
ca.uhn.fhir.rest.api.server.RequestDetails theRequestDetails,
@Description(shortDefinition="Search the contents of the resource's data using a filter")
@OperationParam(name=ca.uhn.fhir.rest.api.Constants.PARAM_FILTER)
StringAndListParam theFtFilter,
@Description(shortDefinition="Search the contents of the resource's data using a fulltext search")
@OperationParam(name=ca.uhn.fhir.rest.api.Constants.PARAM_CONTENT)
StringAndListParam theFtContent,
@Description(shortDefinition="Search the contents of the resource's narrative using a fulltext search")
@OperationParam(name=ca.uhn.fhir.rest.api.Constants.PARAM_TEXT)
StringAndListParam theFtText,
@Description(shortDefinition="The classification of the type of observation")
@OperationParam(name="category")
TokenAndListParam theCategory,
@Description(shortDefinition="The code of the observation type")
@OperationParam(name="code")
TokenAndListParam theCode,
@Description(shortDefinition="Obtained date/time. If the obtained element is a period, a date that falls in the period")
@OperationParam(name="date")
DateRangeParam theDate,
@Description(shortDefinition="The subject that the observation is about (if patient)")
@OperationParam(name="patient")
ReferenceAndListParam thePatient,
@Description(shortDefinition="The subject that the observation is about")
@OperationParam(name="subject" )
ReferenceAndListParam theSubject,
@IncludeParam(reverse=true)
Set<Include> theRevIncludes,
@Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name="_lastUpdated")
DateRangeParam theLastUpdated,
@IncludeParam(allow= {
"Observation:based-on",
"Observation:derived-from",
"Observation:device",
"Observation:encounter",
"Observation:focus",
"Observation:has-member",
"Observation:part-of",
"Observation:patient",
"Observation:performer",
"Observation:specimen",
"Observation:subject",
"*"
})
Set<Include> theIncludes,
@Sort
SortSpec theSort,
@ca.uhn.fhir.rest.annotation.Count
Integer theCount,
SummaryEnum theSummaryMode,
SearchTotalModeEnum theSearchTotalMode
) {
startRequest(theServletRequest);
try {
SearchParameterMap paramMap = new SearchParameterMap();
paramMap.add(ca.uhn.fhir.rest.api.Constants.PARAM_FILTER, theFtFilter);
paramMap.add(ca.uhn.fhir.rest.api.Constants.PARAM_CONTENT, theFtContent);
paramMap.add(ca.uhn.fhir.rest.api.Constants.PARAM_TEXT, theFtText);
paramMap.add("category", theCategory);
paramMap.add("code", theCode);
paramMap.add("date", theDate);
paramMap.add("patient", thePatient);
paramMap.add("subject", theSubject);
paramMap.setRevIncludes(theRevIncludes);
paramMap.setLastUpdated(theLastUpdated);
paramMap.setIncludes(theIncludes);
paramMap.setLastN(true);
if (theSort == null) {
SortSpec effectiveDtm = new SortSpec("date").setOrder(SortOrderEnum.DESC);
SortSpec observationCode = new SortSpec("code").setOrder(SortOrderEnum.ASC).setChain(effectiveDtm);
if (thePatient != null && theSubject == null) {
theSort = new SortSpec("patient").setChain(observationCode);
} else {
theSort = new SortSpec("subject").setChain(observationCode);
}
}
paramMap.setSort(theSort);
paramMap.setCount(theCount);
paramMap.setSummaryMode(theSummaryMode);
paramMap.setSearchTotalMode(theSearchTotalMode);
return ((IFhirResourceDaoObservation) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
} finally {
endRequest(theServletRequest);
}
}
}

View File

@ -1,19 +0,0 @@
package ca.uhn.fhir.jpa.search.lastn.json;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
public class IdJson {
@JsonProperty(value = "_id", required = true)
private String myId;
public IdJson(String theId) {
myId = theId;
}
public String getId() { return myId; }
}

View File

@ -1,20 +0,0 @@
package ca.uhn.fhir.jpa.search.lastn.json;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
public class IndexJson {
@JsonProperty(value = "index", required = true)
private IdJson myIndex;
public IndexJson(IdJson theIndex) {
myIndex = theIndex;
}
public IdJson getId() { return myIndex; }
}

View File

@ -1,18 +0,0 @@
package ca.uhn.fhir.jpa.search.lastn.util;
public class SimpleStopWatch {
private long myStarted = System.currentTimeMillis();
public SimpleStopWatch() {
}
public long getElapsedTime() {
return System.currentTimeMillis() - myStarted;
}
public void restart() {
myStarted = System.currentTimeMillis();
}
}

View File

@ -28,7 +28,7 @@ import static org.mockito.Mockito.when;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestR4ConfigWithElasticsearchClient.class })
public class FhirResourceDaoR4SearchLastNTest extends BaseJpaTest {
public class FhirResourceDaoR4SearchLastNIT extends BaseJpaTest {
@Autowired
@Qualifier("myPatientDaoR4")

View File

@ -60,10 +60,10 @@ import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestR4ConfigWithElasticSearch.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class FhirResourceDaoR4SearchWithElasticSearchTest extends BaseJpaTest {
public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest {
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4SearchWithElasticSearchTest.class);
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4SearchWithElasticSearchIT.class);
@Autowired
protected DaoConfig myDaoConfig;
@Autowired

View File

@ -40,7 +40,7 @@ import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestR4ConfigWithElasticsearchClient.class})
public class PersistObservationIndexedSearchParamLastNR4Test {
public class PersistObservationIndexedSearchParamLastNR4IT {
@Autowired
IObservationIndexedSearchParamLastNDao myResourceIndexedObservationLastNDao;
@ -48,9 +48,6 @@ public class PersistObservationIndexedSearchParamLastNR4Test {
@Autowired
IObservationIndexedCodeCodeableConceptSearchParamDao myCodeableConceptIndexedSearchParamNormalizedDao;
// @Autowired
// ObservationLastNIndexPersistR4Svc myObservationLastNIndexPersistR4Svc;
@Autowired
private ElasticsearchSvcImpl elasticsearchSvc;
@ -68,9 +65,6 @@ public class PersistObservationIndexedSearchParamLastNR4Test {
myResourceIndexedObservationLastNDao.deleteAll();
myCodeableConceptIndexedSearchParamNormalizedDao.deleteAll();
// testObservationPersist = new BaseObservationLastNIndexPersistSvc(myEntityManager, myResourceIndexedObservationLastNDao,
// myObservationIndexedCodeCodingSearchParamDao, mySearchParamExtractor, myContext);
}

View File

@ -26,7 +26,7 @@ import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestElasticsearchConfig.class})
public class LastNElasticsearchSvcMultipleObservationsTest {
public class LastNElasticsearchSvcMultipleObservationsIT {
@Autowired
private ElasticsearchSvcImpl elasticsearchSvc;

View File

@ -27,7 +27,7 @@ import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestElasticsearchConfig.class})
public class LastNElasticsearchSvcSingleObservationTest {
public class LastNElasticsearchSvcSingleObservationIT {
@Autowired
ElasticsearchSvcImpl elasticsearchSvc;

View File

@ -636,7 +636,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
}
private void addToken_Coding(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
theParams.add(createSearchParamForCoding(theResourceType, theSearchParam, theValue));
ResourceIndexedSearchParamToken resourceIndexedSearchParamToken = createSearchParamForCoding(theResourceType, theSearchParam, theValue);
if (resourceIndexedSearchParamToken != null) {
theParams.add(resourceIndexedSearchParamToken);
}
String text = getDisplayTextForCoding(theValue);
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text);

View File

@ -164,7 +164,7 @@ public class FhirAutoConfiguration {
private ScheduledExecutorService myScheduledExecutorService;
@Configuration
@EntityScan(basePackages = {"ca.uhn.fhir.jpa.entity", "ca.uhn.fhir.jpa.model.entity"})
@EntityScan(basePackages = {"ca.uhn.fhir.jpa.entity", "ca.uhn.fhir.jpa.model.entity", "ca.uhn.fhir.jpa.dao.lastn.entity"})
@Import({
SubscriptionChannelConfig.class,
SubscriptionProcessorConfig.class,

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
public class ${className}ResourceProvider extends
## We have specialized base classes for RPs that handle certain resource types. These
## RPs implement type specific operations
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap') || ${className} == 'MessageHeader' || ${className} == 'Composition' || ${className} == 'StructureDefinition' || ${className} == 'Observation' ))
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap') || ${className} == 'MessageHeader' || ${className} == 'Composition' || ${className} == 'StructureDefinition' || ($version != 'dstu2' && ${className} == 'Observation') ))
BaseJpaResourceProvider${className}${versionCapitalized}
#else
JpaResourceProvider${versionCapitalized}<${className}>