diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java index c79ce66547a..30d9439b417 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java @@ -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")) { diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index 2509802ef16..9988c9b8aba 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -136,10 +136,6 @@ - - org.postgresql - postgresql - diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java index 5968d9ef739..7e3eb9fecf1 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java @@ -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; - } - } diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java index 40b8e8f1e57..2211b0ee469 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java @@ -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(); diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index af0cee2d749..ba1e3d61c74 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -640,6 +640,28 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.2 + + true + 1 + false + alphabetical + + **/*IT.java + + + + + + integration-test + verify + + + + de.jpdigital hibernate54-ddl-maven-plugin diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java index 9e0d0207beb..bd6b9dc0a84 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java index 11730fbf192..4034e720a63 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java index 88e73510b39..615272a4e9c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 68add2eb3de..35d03ae2c2e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -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 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 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 lastnPids = new ArrayList<>(); - List 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 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 lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myMaxObservationsPerCode); for (String lastnResourceId : lastnResourceIds) { - lastnPids.add(myIdHelperService.resolveResourcePersistentIds(myResourceName, lastnResourceId)); + pids.add(myIdHelperService.resolveResourcePersistentIds(myResourceName, lastnResourceId)); } } - } - - // - List pids; - if (fullTextSearchPids.isEmpty()) { - pids = lastnPids; - } else if (lastnPids.isEmpty()) { - pids = fullTextSearchPids; - } else { - // Intersection of the fullTextSearchPids and lastnPids - Set 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))); + } /* diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistDstu3Svc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistDstu3Svc.java deleted file mode 100644 index 5834d1bb5d7..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistDstu3Svc.java +++ /dev/null @@ -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 categoryConcepts = new HashSet<>(); - for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) { - // Build Coding entities for each category CodeableConcept - Set 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); - } - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR4Svc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR4Svc.java deleted file mode 100644 index d1d1f45e439..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR4Svc.java +++ /dev/null @@ -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 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 categoryConcepts = new HashSet<>(); - for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) { - // Build Coding entities for each category CodeableConcept - Set 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); - } - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR5Svc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR5Svc.java deleted file mode 100644 index 176d35ce7d5..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistR5Svc.java +++ /dev/null @@ -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 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 categoryConcepts = new HashSet<>(); - for(CodeableConcept categoryCodeableConcept : theObservation.getCategory()) { - // Build Coding entities for each category CodeableConcept - Set 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); - } - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistSvc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistSvc.java index a906f852002..105fc81efda 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistSvc.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/ObservationLastNIndexPersistSvc.java @@ -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 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 observationCategoryCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.category", theResource); - Set 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 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 observationCategoryCodeableConcepts = mySearchParameterExtractor.extractValues("Observation.category", theResource); + Set 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) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/entity/ObservationIndexedCodeCodeableConceptEntity.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/entity/ObservationIndexedCodeCodeableConceptEntity.java index bf1d994d31d..2757173505d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/entity/ObservationIndexedCodeCodeableConceptEntity.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/lastn/entity/ObservationIndexedCodeCodeableConceptEntity.java @@ -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")) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoObservationR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoObservationR4.java index 14828dd2727..55f47758b3f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoObservationR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoObservationR4.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderObservationDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderObservationDstu2.java deleted file mode 100644 index 9a61f635368..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderObservationDstu2.java +++ /dev/null @@ -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/$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 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 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); - } - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IdJson.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IdJson.java deleted file mode 100644 index 1df4410f054..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IdJson.java +++ /dev/null @@ -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; } -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IndexJson.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IndexJson.java deleted file mode 100644 index dc1880124b4..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/json/IndexJson.java +++ /dev/null @@ -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; } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/util/SimpleStopWatch.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/util/SimpleStopWatch.java deleted file mode 100644 index 20381a5e2fe..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/util/SimpleStopWatch.java +++ /dev/null @@ -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(); - } - -} diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNIT.java similarity index 99% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNTest.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNIT.java index c63a1a8932e..58f16a68383 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchLastNIT.java @@ -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") diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java similarity index 98% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java index 7c6bcca1295..85e53af4ad6 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java @@ -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 diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4IT.java similarity index 98% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4Test.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4IT.java index 79f08459135..9a552c09a0d 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/PersistObservationIndexedSearchParamLastNR4IT.java @@ -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); - } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsIT.java similarity index 99% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsTest.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsIT.java index 2f495cdea88..7eb78281ec3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcMultipleObservationsIT.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationIT.java similarity index 99% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationTest.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationIT.java index e2dc8f23bb8..b78e14821b3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/lastn/LastNElasticsearchSvcSingleObservationIT.java @@ -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; diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java index 8a73cdf1349..78d54ead1eb 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java @@ -636,7 +636,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor } private void addToken_Coding(String theResourceType, Set 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); diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java index c84e17cad24..91566fc9527 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java @@ -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, diff --git a/hapi-tinder-plugin/src/main/resources/vm/jpa_resource_provider.vm b/hapi-tinder-plugin/src/main/resources/vm/jpa_resource_provider.vm index 665f598fd98..737dfb1fb04 100644 --- a/hapi-tinder-plugin/src/main/resources/vm/jpa_resource_provider.vm +++ b/hapi-tinder-plugin/src/main/resources/vm/jpa_resource_provider.vm @@ -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}>