More cleanup and test fixes.
This commit is contained in:
parent
197bf2b6a8
commit
0e45db0ba9
|
@ -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")) {
|
||||
|
|
|
@ -136,10 +136,6 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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; }
|
||||
}
|
|
@ -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; }
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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")
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}>
|
||||
|
|
Loading…
Reference in New Issue