diff --git a/fhir-database-utils/src/main/java/org/linuxforhealth/fhir/database/utils/common/DataDefinitionUtil.java b/fhir-database-utils/src/main/java/org/linuxforhealth/fhir/database/utils/common/DataDefinitionUtil.java index 3bacdfafb38..ffd585e6e77 100644 --- a/fhir-database-utils/src/main/java/org/linuxforhealth/fhir/database/utils/common/DataDefinitionUtil.java +++ b/fhir-database-utils/src/main/java/org/linuxforhealth/fhir/database/utils/common/DataDefinitionUtil.java @@ -21,7 +21,7 @@ * Handles common syntax for generating DDL */ public class DataDefinitionUtil { - private static final String NAME_PATTERN_RGX = "[a-zA-Z_][-\\w]*$"; + private static final String NAME_PATTERN_RGX = "[a-zA-Z_][\\w]*$"; private static final Pattern NAME_PATTERN = Pattern.compile(NAME_PATTERN_RGX); /** diff --git a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/api/ResourceDAO.java b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/api/ResourceDAO.java index 5d2d963c767..913eee37906 100644 --- a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/api/ResourceDAO.java +++ b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/api/ResourceDAO.java @@ -11,6 +11,7 @@ import java.util.Map; import org.linuxforhealth.fhir.database.utils.query.Select; +import org.linuxforhealth.fhir.persistence.HistorySortOrder; import org.linuxforhealth.fhir.persistence.context.FHIRPersistenceContext; import org.linuxforhealth.fhir.persistence.exception.FHIRPersistenceDataAccessException; import org.linuxforhealth.fhir.persistence.exception.FHIRPersistenceException; @@ -60,7 +61,7 @@ Resource versionRead(String logicalId, String resourceType, int versionId) * @throws FHIRPersistenceDataAccessException * @throws FHIRPersistenceDBConnectException */ - List history(String resourceType, String logicalId, Timestamp fromDateTime, int offset, int maxResults) + List history(String resourceType, String logicalId, Timestamp fromDateTime, int offset, int maxResults, HistorySortOrder historySortOrder) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException; /** @@ -184,8 +185,8 @@ List search(String sqlSelect) * @throws FHIRPersistenceVersionIdMismatchException * @throws FHIRPersistenceException */ - Resource insert(Resource resource, List parameters, String parameterHashB64, ParameterDAO parameterDao, - Integer ifNoneMatch) + Resource insert(Resource resource, List parameters, String parameterHashB64, ParameterDAO parameterDao, + Integer ifNoneMatch) throws FHIRPersistenceException; /** diff --git a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/impl/ResourceDAOImpl.java b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/impl/ResourceDAOImpl.java index 299d35ceabf..7311e32d70f 100644 --- a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/impl/ResourceDAOImpl.java +++ b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/dao/impl/ResourceDAOImpl.java @@ -31,6 +31,7 @@ import org.linuxforhealth.fhir.database.utils.common.CalendarHelper; import org.linuxforhealth.fhir.database.utils.query.QueryUtil; import org.linuxforhealth.fhir.database.utils.query.Select; +import org.linuxforhealth.fhir.persistence.HistorySortOrder; import org.linuxforhealth.fhir.persistence.context.FHIRPersistenceContext; import org.linuxforhealth.fhir.persistence.exception.FHIRPersistenceDataAccessException; import org.linuxforhealth.fhir.persistence.exception.FHIRPersistenceException; @@ -80,7 +81,7 @@ public abstract class ResourceDAOImpl extends FHIRDbDAOImpl implements ResourceD "SELECT R.RESOURCE_ID, R.LOGICAL_RESOURCE_ID, R.VERSION_ID, R.LAST_UPDATED, R.IS_DELETED, R.DATA, LR.LOGICAL_ID, R.RESOURCE_PAYLOAD_KEY " + "FROM %s_RESOURCES R, %s_LOGICAL_RESOURCES LR WHERE " + "LR.LOGICAL_ID = ? AND R.LOGICAL_RESOURCE_ID = LR.LOGICAL_RESOURCE_ID " + - "ORDER BY R.VERSION_ID DESC "; + "ORDER BY R.VERSION_ID %s "; // Count the number of versions we have for the resource identified by its logical-id private static final String SQL_HISTORY_COUNT = "SELECT COUNT(R.VERSION_ID) FROM %s_RESOURCES R, %s_LOGICAL_RESOURCES LR WHERE LR.LOGICAL_ID = ? AND " + @@ -90,7 +91,7 @@ public abstract class ResourceDAOImpl extends FHIRDbDAOImpl implements ResourceD "SELECT R.RESOURCE_ID, R.LOGICAL_RESOURCE_ID, R.VERSION_ID, R.LAST_UPDATED, R.IS_DELETED, R.DATA, LR.LOGICAL_ID, R.RESOURCE_PAYLOAD_KEY " + "FROM %s_RESOURCES R, %s_LOGICAL_RESOURCES LR WHERE " + "LR.LOGICAL_ID = ? AND R.LAST_UPDATED >= ? AND R.LOGICAL_RESOURCE_ID = LR.LOGICAL_RESOURCE_ID " + - "ORDER BY R.VERSION_ID DESC "; + "ORDER BY R.VERSION_ID %s "; private static final String SQL_HISTORY_FROM_DATETIME_COUNT = "SELECT COUNT(R.VERSION_ID) FROM %s_RESOURCES R, %s_LOGICAL_RESOURCES LR WHERE LR.LOGICAL_ID = ? AND " + @@ -147,7 +148,7 @@ public abstract class ResourceDAOImpl extends FHIRDbDAOImpl implements ResourceD * @param trxSyncRegistry */ public ResourceDAOImpl(Connection c, String schemaName, FHIRDbFlavor flavor, TransactionSynchronizationRegistry trxSynchRegistry, - FHIRPersistenceJDBCCache cache, ParameterTransactionDataImpl ptdi) { + FHIRPersistenceJDBCCache cache, ParameterTransactionDataImpl ptdi) { super(c, schemaName, flavor); this.runningInTrx = true; this.trxSynchRegistry = trxSynchRegistry; @@ -251,7 +252,7 @@ protected Resource createDTO(ResultSet resultSet, boolean hasResourceTypeId) thr resource.setVersionId(resultSet.getInt(IDX_VERSION_ID)); resource.setDeleted(resultSet.getString(IDX_IS_DELETED).equals("Y") ? true : false); resource.setResourcePayloadKey(resultSet.getString(IDX_RESOURCE_PAYLOAD_KEY)); - + if (hasResourceTypeId) { resource.setResourceTypeId(resultSet.getInt(IDX_RESOURCE_TYPE_ID)); } @@ -266,7 +267,7 @@ protected Resource createDTO(ResultSet resultSet, boolean hasResourceTypeId) thr } @Override - public List history(String resourceType, String logicalId, Timestamp fromDateTime, int offset, int maxResults) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { + public List history(String resourceType, String logicalId, Timestamp fromDateTime, int offset, int maxResults, HistorySortOrder sortOrder) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { final String METHODNAME = "history"; log.entering(CLASSNAME, METHODNAME); @@ -274,12 +275,19 @@ public List history(String resourceType, String logicalId, Timestamp f String stmtString = null; try { + final String sortDirection; + if(HistorySortOrder.ASC_LAST_UPDATED.equals(sortOrder)){ + sortDirection="Asc"; + }else{ + sortDirection="Desc"; + } + if (fromDateTime != null) { - stmtString = String.format(SQL_HISTORY_FROM_DATETIME, resourceType, resourceType); + stmtString = String.format(SQL_HISTORY_FROM_DATETIME, resourceType, resourceType,sortDirection); stmtString = stmtString + DERBY_PAGINATION_PARMS; resources = this.runQuery(stmtString, logicalId, fromDateTime, offset, maxResults); } else { - stmtString = String.format(SQL_HISTORY, resourceType, resourceType); + stmtString = String.format(SQL_HISTORY, resourceType, resourceType,sortDirection); stmtString = stmtString + DERBY_PAGINATION_PARMS; resources = this.runQuery(stmtString, logicalId, offset, maxResults); } @@ -409,7 +417,7 @@ protected Integer getResourceTypeId(String resourceType) throws FHIRPersistenceE } // cache miss, so read from the database resourceTypeId = this.readResourceTypeId(resourceType); - + if (resourceTypeId != null) { cache.getResourceTypeCache().addEntry(resourceType, resourceTypeId); cache.getResourceTypeNameCache().addEntry(resourceTypeId, resourceType); @@ -553,7 +561,7 @@ protected FHIRPersistenceJDBCCache getCache() { @Override public int searchCount(Select countQuery) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { return runCountQuery(countQuery); - } + } @Override public List search(Select select) throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { diff --git a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java index 5b95f9ed61c..ded8b71a3b3 100644 --- a/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java +++ b/fhir-persistence-jdbc/src/main/java/org/linuxforhealth/fhir/persistence/jdbc/impl/FHIRPersistenceJDBCImpl.java @@ -349,7 +349,7 @@ public FHIRPersistenceJDBCImpl(Properties configProps, IConnectionProvider cp, F * @throws Exception */ public FHIRPersistenceJDBCImpl(Properties configProps, IConnectionProvider cp, FHIRConfigProvider configProvider, - FHIRPersistenceJDBCCache cache, SearchHelper searchHelper) throws Exception { + FHIRPersistenceJDBCCache cache, SearchHelper searchHelper) throws Exception { final String METHODNAME = "FHIRPersistenceJDBCImpl(Properties, IConnectionProvider, FHIRConfigProvider)"; log.entering(CLASSNAME, METHODNAME); @@ -410,7 +410,7 @@ public SingleResourceResult create(FHIRPersistenceContex log.entering(CLASSNAME, METHODNAME); try (Connection connection = openConnection(); - MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_CREATE.name())) { + MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_CREATE.name())) { doCachePrefill(context, connection); if (context.getOffloadResponse() != null) { @@ -434,7 +434,7 @@ public SingleResourceResult create(FHIRPersistenceContex // Create the new Resource DTO instance. org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO = createResourceDTO(updatedResource.getClass(), logicalId, newVersionNumber, lastUpdated, updatedResource, - getResourcePayloadKeyFromContext(context)); + getResourcePayloadKeyFromContext(context)); // The DAO objects are now created on-the-fly (not expensive to construct) and // given the connection to use while processing this request @@ -450,13 +450,13 @@ public SingleResourceResult create(FHIRPersistenceContex resourceDao.insert(resourceDTO, searchParameters.getParameters(), searchParameters.getParameterHashB64(), parameterDao, context.getIfNoneMatch()); if (log.isLoggable(Level.FINE)) { log.fine("Persisted FHIR Resource '" + resourceDTO.getResourceType() + "/" + resourceDTO.getLogicalId() + "' logicalResourceId=" + resourceDTO.getLogicalResourceId() - + ", version=" + resourceDTO.getVersionId()); + + ", version=" + resourceDTO.getVersionId()); } if (resourceDTO.getInteractionStatus() == InteractionStatus.MODIFIED && searchParameters != null) { storeSearchParameterValues(resourceDTO.getResourceType(), resourceDTO.getLogicalId(), resourceDTO.getLogicalResourceId(), - resourceDTO.getVersionId(), resourceDTO.getLastUpdated().toInstant(), context.getRequestShard(), searchParameters, - resourceDTO.getCurrentParameterHash()); + resourceDTO.getVersionId(), resourceDTO.getLastUpdated().toInstant(), context.getRequestShard(), searchParameters, + resourceDTO.getCurrentParameterHash()); } SingleResourceResult.Builder resultBuilder = new SingleResourceResult.Builder() .success(true) @@ -467,8 +467,8 @@ public SingleResourceResult create(FHIRPersistenceContex // Add supplemental issues to the OperationOutcome if (!supplementalIssues.isEmpty()) { resultBuilder.outcome(OperationOutcome.builder() - .issue(supplementalIssues) - .build()); + .issue(supplementalIssues) + .build()); } return resultBuilder.build(); @@ -487,7 +487,7 @@ public SingleResourceResult create(FHIRPersistenceContex throw fx; } finally { - log.exiting(CLASSNAME, METHODNAME); + log.exiting(CLASSNAME, METHODNAME); } } @@ -505,8 +505,8 @@ public SingleResourceResult create(FHIRPersistenceContex * @param currentParameterHash the current parameter hash returned from add_any_resource (null if this is a new resource) */ private void storeSearchParameterValues(String resourceType, String logicalId, long logicalResourceId, - int versionId, java.time.Instant lastUpdated, String requestShard, - ExtractedSearchParameters searchParameters, String currentParameterHash) throws FHIRPersistenceException { + int versionId, java.time.Instant lastUpdated, String requestShard, + ExtractedSearchParameters searchParameters, String currentParameterHash) throws FHIRPersistenceException { final SearchParametersTransportAdapter adapter = buildSearchParametersTransportAdapter(resourceType, logicalId, logicalResourceId, versionId, lastUpdated, requestShard, searchParameters, currentParameterHash); @@ -516,7 +516,7 @@ private void storeSearchParameterValues(String resourceType, String logicalId, l // Store the search parameters locally as part of the current transaction final String parameterHashB64 = searchParameters.getParameterHashB64(); if (parameterHashB64 == null || parameterHashB64.isEmpty() - || !parameterHashB64.equals(currentParameterHash)) { + || !parameterHashB64.equals(currentParameterHash)) { accumulateSearchParameterValues(adapter.build()); } } else { @@ -546,11 +546,11 @@ private void storeSearchParameterValues(String resourceType, String logicalId, l * @return */ private SearchParametersTransportAdapter buildSearchParametersTransportAdapter(String resourceType, String logicalId, long logicalResourceId, - int versionId, java.time.Instant lastUpdated, String requestShard, - ExtractedSearchParameters searchParameters, String currentParameterHash) throws FHIRPersistenceException { + int versionId, java.time.Instant lastUpdated, String requestShard, + ExtractedSearchParameters searchParameters, String currentParameterHash) throws FHIRPersistenceException { SearchParametersTransportAdapter adapter = new SearchParametersTransportAdapter(resourceType, logicalId, logicalResourceId, - versionId, lastUpdated, requestShard, searchParameters.getParameterHashB64()); + versionId, lastUpdated, requestShard, searchParameters.getParameterHashB64()); ParameterTransportVisitor visitor = new ParameterTransportVisitor(adapter); for (ExtractedParameterValue pv: searchParameters.getParameters()) { pv.accept(visitor); @@ -660,8 +660,8 @@ private void doCachePrefill() throws FHIRPersistenceException { * @throws FHIRGeneratorException */ private org.linuxforhealth.fhir.persistence.jdbc.dto.Resource createResourceDTO(Class resourceType, - String logicalId, int newVersionNumber, - Instant lastUpdated, Resource updatedResource, String resourcePayloadKey) throws IOException, FHIRGeneratorException { + String logicalId, int newVersionNumber, + Instant lastUpdated, Resource updatedResource, String resourcePayloadKey) throws IOException, FHIRGeneratorException { Timestamp timestamp = FHIRUtilities.convertToTimestamp(lastUpdated.getValue()); @@ -779,7 +779,7 @@ public SingleResourceResult update(FHIRPersistenceContex log.entering(CLASSNAME, METHODNAME); try (Connection connection = openConnection(); - MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_UPDATE.name())) { + MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_UPDATE.name())) { doCachePrefill(context, connection); if (context.getOffloadResponse() != null) { @@ -796,8 +796,8 @@ public SingleResourceResult update(FHIRPersistenceContex // Create the new Resource DTO instance. org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO = createResourceDTO(resource.getClass(), resource.getId(), newVersionNumber, - resource.getMeta().getLastUpdated(), resource, - getResourcePayloadKeyFromContext(context)); + resource.getMeta().getLastUpdated(), resource, + getResourcePayloadKeyFromContext(context)); // Persist the Resource DTO. resourceDao.setPersistenceContext(context); @@ -808,19 +808,19 @@ public SingleResourceResult update(FHIRPersistenceContex if (log.isLoggable(Level.FINE)) { if (resourceDTO.getInteractionStatus() == InteractionStatus.IF_NONE_MATCH_EXISTED) { log.fine("If-None-Match: Existing FHIR Resource '" + resourceDTO.getResourceType() + "/" + resourceDTO.getLogicalId() + "' logicalResourceId=" + resourceDTO.getLogicalResourceId() - + ", version=" + resourceDTO.getVersionId()); + + ", version=" + resourceDTO.getVersionId()); } else { log.fine("Persisted FHIR Resource '" + resourceDTO.getResourceType() + "/" + resourceDTO.getLogicalId() + "' logicalResourceId=" + resourceDTO.getLogicalResourceId() - + ", version=" + resourceDTO.getVersionId()); + + ", version=" + resourceDTO.getVersionId()); } } // If configured, send the extracted parameters to the remote indexing service if (resourceDTO.getInteractionStatus() == InteractionStatus.MODIFIED && searchParameters != null) { storeSearchParameterValues(resourceDTO.getResourceType(), resourceDTO.getLogicalId(), resourceDTO.getLogicalResourceId(), - resourceDTO.getVersionId(), resourceDTO.getLastUpdated().toInstant(), context.getRequestShard(), searchParameters, - resourceDTO.getCurrentParameterHash() - ); + resourceDTO.getVersionId(), resourceDTO.getLastUpdated().toInstant(), context.getRequestShard(), searchParameters, + resourceDTO.getCurrentParameterHash() + ); } SingleResourceResult.Builder resultBuilder = new SingleResourceResult.Builder() @@ -832,8 +832,8 @@ public SingleResourceResult update(FHIRPersistenceContex // Add supplemental issues to an OperationOutcome if (!supplementalIssues.isEmpty()) { resultBuilder.outcome(OperationOutcome.builder() - .issue(supplementalIssues) - .build()); + .issue(supplementalIssues) + .build()); } return resultBuilder.build(); @@ -905,8 +905,8 @@ public MultiResourceResult search(FHIRPersistenceContext context, Class issues = validatePagingContext(searchContext); if (!issues.isEmpty()) { resultBuilder.outcome(OperationOutcome.builder() - .issue(issues) - .build()); + .issue(issues) + .build()); if (!searchContext.isLenient()) { return resultBuilder.success(false).build(); } @@ -926,17 +926,17 @@ public MultiResourceResult search(FHIRPersistenceContext context, Class - validateExpectedSearchPagingResults(List resourceDTOList, FHIRSearchContext searchContext, Builder resultBuilder) { + validateExpectedSearchPagingResults(List resourceDTOList, FHIRSearchContext searchContext, Builder resultBuilder) { org.linuxforhealth.fhir.persistence.jdbc.dto.Resource firstResourceResult = null; org.linuxforhealth.fhir.persistence.jdbc.dto.Resource lastResourceResult = null; if (resourceDTOList != null && !resourceDTOList.isEmpty()) { if (resourceDTOList.size() > 0 && searchContext.getPageNumber() != 1) { resultBuilder.expectedPreviousId(resourceDTOList.get(0).getResourceId()); resourceDTOList.remove(0); - } + } if (resourceDTOList.size() > searchContext.getPageSize()) { resultBuilder.expectedNextId(resourceDTOList.get(resourceDTOList.size() - 1).getResourceId()); resourceDTOList.remove(resourceDTOList.size() - 1); @@ -1034,12 +1034,12 @@ public MultiResourceResult search(FHIRPersistenceContext context, Class 0) { resultBuilder.firstId(resourceDTOList.get(0).getResourceId()); @@ -1063,8 +1063,8 @@ public MultiResourceResult search(FHIRPersistenceContext context, Class newSearchForIncludeResources(FHIRSearchContext searchContext, - Class resourceType, NewQueryBuilder queryBuilder, ResourceDAO resourceDao, - List resourceDTOList, SchemaType schemaType) throws Exception { + Class resourceType, NewQueryBuilder queryBuilder, ResourceDAO resourceDao, + List resourceDTOList, SchemaType schemaType) throws Exception { List allIncludeResources = new ArrayList<>(); @@ -1089,7 +1089,7 @@ private List newSearchFor // Build and run the query List includeResources = this.runIncludeQuery(resourceType, searchContext, queryBuilder, includeParm, SearchConstants.INCLUDE, - baseLogicalResourceIds, queryResultMap, resourceDao, 1, allResourceIds, schemaType); + baseLogicalResourceIds, queryResultMap, resourceDao, 1, allResourceIds, schemaType); // Add new ids to de-dup list allResourceIds.addAll(includeResources.stream().map(r -> r.getResourceId()).collect(Collectors.toSet())); @@ -1111,7 +1111,7 @@ private List newSearchFor // Build and run the query List revincludeResources = this.runIncludeQuery(resourceType, searchContext, queryBuilder, revincludeParm, SearchConstants.REVINCLUDE, - baseLogicalResourceIds, queryResultMap, resourceDao, 1, allResourceIds, schemaType); + baseLogicalResourceIds, queryResultMap, resourceDao, 1, allResourceIds, schemaType); // Add new ids to de-dup list allResourceIds.addAll(revincludeResources.stream().map(r -> r.getResourceId()).collect(Collectors.toSet())); @@ -1155,7 +1155,7 @@ private List newSearchFor // Build and run the query List includeResources = this.runIncludeQuery(resourceType, searchContext, queryBuilder, includeParm, - SearchConstants.INCLUDE, queryIds, queryResultMap, resourceDao, i+1, allResourceIds, schemaType); + SearchConstants.INCLUDE, queryIds, queryResultMap, resourceDao, i+1, allResourceIds, schemaType); // Add new ids to de-dup list allResourceIds.addAll(includeResources.stream().map(r -> r.getResourceId()).collect(Collectors.toSet())); @@ -1180,7 +1180,7 @@ private List newSearchFor // Build and run the query List revincludeResources = this.runIncludeQuery(resourceType, searchContext, queryBuilder, revincludeParm, - SearchConstants.REVINCLUDE, queryIds, queryResultMap, resourceDao, i+1, allResourceIds, schemaType); + SearchConstants.REVINCLUDE, queryIds, queryResultMap, resourceDao, i+1, allResourceIds, schemaType); // Add new ids to de-dup list allResourceIds.addAll(revincludeResources.stream().map(r -> r.getResourceId()).collect(Collectors.toSet())); @@ -1222,9 +1222,9 @@ private List newSearchFor * @throws Exception */ private List runIncludeQuery(Class resourceType, - FHIRSearchContext searchContext, NewQueryBuilder queryBuilder, InclusionParameter inclusionParm, - String includeType, Set queryIds, Map>> queryResultMap, - ResourceDAO resourceDao, int iterationLevel, Set allResourceIds, SchemaType schemaType) throws Exception { + FHIRSearchContext searchContext, NewQueryBuilder queryBuilder, InclusionParameter inclusionParm, + String includeType, Set queryIds, Map>> queryResultMap, + ResourceDAO resourceDao, int iterationLevel, Set allResourceIds, SchemaType schemaType) throws Exception { if (queryIds.isEmpty()) { return Collections.emptyList(); @@ -1295,9 +1295,9 @@ private FHIRPersistenceNotSupportedException buildNotSupportedException(String m .severity(IssueSeverity.FATAL) .code(IssueType.NOT_SUPPORTED.toBuilder() .extension(Extension.builder() - .url(FHIRConstants.EXT_BASE + "not-supported-detail") - .value(Code.of("interaction")) - .build()) + .url(FHIRConstants.EXT_BASE + "not-supported-detail") + .value(Code.of("interaction")) + .build()) .build()) .details(CodeableConcept.builder().text(string(msg)).build()) .build()); @@ -1305,7 +1305,7 @@ private FHIRPersistenceNotSupportedException buildNotSupportedException(String m @Override public void delete(FHIRPersistenceContext context, Class resourceType, String logicalId, int versionId, - org.linuxforhealth.fhir.model.type.Instant lastUpdated) throws FHIRPersistenceException { + org.linuxforhealth.fhir.model.type.Instant lastUpdated) throws FHIRPersistenceException { final String METHODNAME = "delete"; log.entering(CLASSNAME, METHODNAME); @@ -1331,7 +1331,7 @@ public void delete(FHIRPersistenceContext context, Class if (log.isLoggable(Level.FINE)) { log.fine("Deleted FHIR Resource '" + resourceDTO.getResourceType() + "/" + resourceDTO.getLogicalId() + "' logicalResourceId=" + resourceDTO.getLogicalResourceId() - + ", version=" + resourceDTO.getVersionId()); + + ", version=" + resourceDTO.getVersionId()); } } catch(FHIRPersistenceException e) { throw e; @@ -1346,7 +1346,7 @@ public void delete(FHIRPersistenceContext context, Class @Override public SingleResourceResult read(FHIRPersistenceContext context, Class resourceType, String logicalId) - throws FHIRPersistenceException { + throws FHIRPersistenceException { final String METHODNAME = "read"; log.entering(CLASSNAME, METHODNAME); @@ -1363,17 +1363,17 @@ public SingleResourceResult read(FHIRPersistenceContext SummaryValueSet summary = searchContext.getSummaryParameter(); switch (summary) { - case TRUE: - summaryElements = JsonSupport.getSummaryElementNames(resourceType); - break; - case TEXT: - summaryElements = SearchHelper.getSummaryTextElementNames(resourceType); - break; - case DATA: - summaryElements = JsonSupport.getSummaryDataElementNames(resourceType); - break; - default: - break; + case TRUE: + summaryElements = JsonSupport.getSummaryElementNames(resourceType); + break; + case TEXT: + summaryElements = SearchHelper.getSummaryTextElementNames(resourceType); + break; + case DATA: + summaryElements = JsonSupport.getSummaryDataElementNames(resourceType); + break; + default: + break; } if (summaryElements != null) { @@ -1384,7 +1384,7 @@ public SingleResourceResult read(FHIRPersistenceContext } try (Connection connection = openConnection(); - MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_READ.name())) { + MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_READ.name())) { doCachePrefill(context, connection); ResourceDAO resourceDao = makeResourceDAO(context, connection); @@ -1423,7 +1423,7 @@ public SingleResourceResult read(FHIRPersistenceContext * @return */ private OperationOutcome getOutcomeIfResourceNotFound(org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO, - String resourceType, String logicalId) { + String resourceType, String logicalId) { if (resourceDTO != null) { return null; } else { @@ -1438,7 +1438,7 @@ private OperationOutcome getOutcomeIfResourceNotFound(org.linuxforhealth.fhir.pe @Override public MultiResourceResult history(FHIRPersistenceContext context, Class resourceType, - String logicalId) throws FHIRPersistenceException { + String logicalId) throws FHIRPersistenceException { final String METHODNAME = "history"; log.entering(CLASSNAME, METHODNAME); @@ -1452,7 +1452,7 @@ public MultiResourceResult history(FHIRPersistenceContext context, Class 0) { offset = (historyContext.getPageNumber() - 1) * historyContext.getPageSize(); - resourceDTOList = resourceDao.history(resourceType.getSimpleName(), logicalId, fromDateTime, offset, historyContext.getPageSize()); + resourceDTOList = resourceDao.history(resourceType.getSimpleName(), logicalId, fromDateTime, offset, historyContext.getPageSize(),historyContext.getHistorySortOrder()); resourceResults = this.convertResourceDTOList(resourceDao, resourceDTOList, resourceType, null, true); } @@ -1515,12 +1515,12 @@ private List validatePagingContext(FHIRPagingContext pag int pageSize = pagingContext.getPageSize(); if (pageSize < 0) { issues.add(OperationOutcome.Issue.builder() - .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) - .code(IssueType.INVALID) - .details(CodeableConcept.builder() - .text(string("Invalid page size: " + pageSize)) - .build()) - .build()); + .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) + .code(IssueType.INVALID) + .details(CodeableConcept.builder() + .text(string("Invalid page size: " + pageSize)) + .build()) + .build()); // Pick a valid default if lenient if (pagingContext.isLenient()) { pagingContext.setPageSize(FHIRConstants.FHIR_PAGE_SIZE_DEFAULT); @@ -1535,24 +1535,24 @@ private List validatePagingContext(FHIRPagingContext pag int pageNumber = pagingContext.getPageNumber(); if (pageNumber < 1) { issues.add(OperationOutcome.Issue.builder() - .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) - .code(IssueType.INVALID) - .details(CodeableConcept.builder() - .text(string("Invalid page number: " + pageNumber)) - .build()) - .build()); + .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) + .code(IssueType.INVALID) + .details(CodeableConcept.builder() + .text(string("Invalid page number: " + pageNumber)) + .build()) + .build()); // Pick a valid default if lenient if (pagingContext.isLenient()) { pagingContext.setPageNumber(FHIRConstants.FHIR_PAGE_NUMBER_DEFAULT); } } else if (pageNumber > lastPageNumber) { issues.add(OperationOutcome.Issue.builder() - .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) - .code(IssueType.INVALID) - .details(CodeableConcept.builder() - .text(string("Specified page number: " + pageNumber + " is greater than last page number: " + lastPageNumber)) - .build()) - .build()); + .severity(pagingContext.isLenient() ? IssueSeverity.WARNING : IssueSeverity.ERROR) + .code(IssueType.INVALID) + .details(CodeableConcept.builder() + .text(string("Specified page number: " + pageNumber + " is greater than last page number: " + lastPageNumber)) + .build()) + .build()); // Set it to the last page if lenient if (pagingContext.isLenient()) { pagingContext.setPageNumber(lastPageNumber); @@ -1568,7 +1568,7 @@ private List validatePagingContext(FHIRPagingContext pag */ @Override public SingleResourceResult vread(FHIRPersistenceContext context, Class resourceType, String logicalId, String versionId) - throws FHIRPersistenceException { + throws FHIRPersistenceException { final String METHODNAME = "vread"; log.entering(CLASSNAME, METHODNAME); @@ -1587,17 +1587,17 @@ public SingleResourceResult vread(FHIRPersistenceContext SummaryValueSet summary = searchContext.getSummaryParameter(); switch (summary) { - case TRUE: - summaryElements = JsonSupport.getSummaryElementNames(resourceType); - break; - case TEXT: - summaryElements = SearchHelper.getSummaryTextElementNames(resourceType); - break; - case DATA: - summaryElements = JsonSupport.getSummaryDataElementNames(resourceType); - break; - default: - break; + case TRUE: + summaryElements = JsonSupport.getSummaryElementNames(resourceType); + break; + case TEXT: + summaryElements = SearchHelper.getSummaryTextElementNames(resourceType); + break; + case DATA: + summaryElements = JsonSupport.getSummaryDataElementNames(resourceType); + break; + default: + break; } if (summaryElements != null) { @@ -1608,7 +1608,7 @@ public SingleResourceResult vread(FHIRPersistenceContext } try (Connection connection = openConnection(); - MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_VREAD.name())) { + MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_VREAD.name())) { doCachePrefill(context, connection); ResourceDAO resourceDao = makeResourceDAO(context, connection); @@ -1650,7 +1650,7 @@ public SingleResourceResult vread(FHIRPersistenceContext * @throws IOException */ protected List buildSortedResourceDTOList(ResourceDAO resourceDao, Class resourceType, List sortedIdList, - boolean includeResourceData) + boolean includeResourceData) throws FHIRException, FHIRPersistenceException, IOException { final String METHOD_NAME = "buildSortedResourceDTOList"; log.entering(this.getClass().getName(), METHOD_NAME); @@ -1697,8 +1697,8 @@ protected List buildSorte * @throws FHIRPersistenceDBConnectException */ private List getResourceDTOs(ResourceDAO resourceDao, - Class resourceType, List sortedIdList, boolean includeResourceData) - throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { + Class resourceType, List sortedIdList, boolean includeResourceData) + throws FHIRPersistenceDataAccessException, FHIRPersistenceDBConnectException { return resourceDao.searchByIds(resourceType.getSimpleName(), sortedIdList, includeResourceData); } @@ -1718,7 +1718,7 @@ private List getResourceD * @throws IOException */ protected List> convertResourceDTOList(ResourceDAO resourceDao, List resourceDTOList, - Class resourceType, List elements, boolean includeResourceData) throws FHIRException, IOException { + Class resourceType, List elements, boolean includeResourceData) throws FHIRException, IOException { final String METHODNAME = "convertResourceDTO List"; log.entering(CLASSNAME, METHODNAME); @@ -1768,8 +1768,8 @@ protected List> convertResourceDTOList(Resour * @param includeResourceData */ private void fetchPayloadsForDTOList(List> resourceResults, - List resourceDTOList, - Class resourceType, List elements, boolean includeResourceData) + List resourceDTOList, + Class resourceType, List elements, boolean includeResourceData) throws FHIRPersistenceException { // Our offloading API supports async, so the first task is to dispatch // all of our requests and then wait for everything to come back. We could @@ -1865,7 +1865,7 @@ private TransactionSynchronizationRegistry getTrxSynchRegistry() throws FHIRPers * @throws Exception */ private ExtractedSearchParameters extractSearchParameters(Resource fhirResource, org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTOx) - throws Exception { + throws Exception { final String METHODNAME = "extractSearchParameters"; log.entering(CLASSNAME, METHODNAME); @@ -1958,9 +1958,9 @@ private ExtractedSearchParameters extractSearchParameters(Resource fhirResource, // However, that would bypass search parameter filtering and so we favor the SeachHelper method here instead. SearchParameter compSP = searchHelper.getSearchParameter(p.getResourceType(), component.getDefinition()); if (compSP == null) { - throw new NullPointerException(String.format("The 'compSP' parameter was " + - "specified to null [ResourceType=%s,Uri=%s]", p.getResourceType(), component.getDefinition())); - } + throw new NullPointerException(String.format("The 'compSP' parameter was " + + "specified to null [ResourceType=%s,Uri=%s]", p.getResourceType(), component.getDefinition())); + } JDBCParameterBuildingVisitor parameterBuilder = new JDBCParameterBuildingVisitor(p.getResourceType(), compSP); FHIRPathNode node = nodes.iterator().next(); if (nodes.size() > 1 ) { @@ -2307,8 +2307,8 @@ protected void addCanonicalCompositeParam(List allParam if (log.isLoggable(Level.FINE)) { log.fine("Adding canonical composite parameter: [" + cp.getResourceType() + "] " + - up.getName() + " = " + up.getValueString() + ", " + - vp.getName() + " = " + vp.getValueString()); + up.getName() + " = " + up.getValueString() + ", " + + vp.getName() + " = " + vp.getValueString()); } allParameters.add(cp); @@ -2466,7 +2466,7 @@ protected UserTransaction retrieveUserTransaction(String jndiName) { * @throws IOException */ protected List convertResourceDTOList(List resourceDTOList, - Class resourceType) throws FHIRException, IOException { + Class resourceType) throws FHIRException, IOException { final String METHODNAME = "convertResourceDTOList"; log.entering(CLASSNAME, METHODNAME); @@ -2494,7 +2494,7 @@ protected List convertResourceDTOList(List T convertResourceDTO(org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO, - Class resourceType, List elements) throws FHIRException, IOException { + Class resourceType, List elements) throws FHIRException, IOException { final String METHODNAME = "convertResourceDTO"; log.entering(CLASSNAME, METHODNAME); T result; @@ -2552,7 +2552,7 @@ private T convertResourceDTO(org.linuxforhealth.fhir.persis } private ResourceResult convertResourceDTOToResourceResult(org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO, - Class resourceType, List elements, boolean includeData) throws FHIRException, IOException { + Class resourceType, List elements, boolean includeData) throws FHIRException, IOException { final String METHODNAME = "convertResourceDTO"; log.entering(CLASSNAME, METHODNAME); Objects.requireNonNull(resourceDTO, "resourceDTO must be not null"); @@ -2627,7 +2627,7 @@ private ResourceResult convertResourceDTOToResourceResul * @return */ private String getResourceTypeInfo(org.linuxforhealth.fhir.persistence.jdbc.dto.Resource resourceDTO) - throws FHIRPersistenceException { + throws FHIRPersistenceException { return getResourceTypeInfo(resourceDTO.getResourceTypeId()); } @@ -2722,8 +2722,8 @@ private void addWarning(IssueType issueType, String message, String... expressio .severity(IssueSeverity.WARNING) .code(issueType) .details(CodeableConcept.builder() - .text(string(message)) - .build()) + .text(string(message)) + .build()) .expression(Arrays.stream(expression).map(org.linuxforhealth.fhir.model.type.String::string).collect(Collectors.toList())) .build()); } @@ -2799,7 +2799,7 @@ public boolean isOffloadingSupported() { @Override public int reindex(FHIRPersistenceContext context, OperationOutcome.Builder operationOutcomeResult, java.time.Instant tstamp, List indexIds, - String resourceLogicalId, boolean force) throws FHIRPersistenceException { + String resourceLogicalId, boolean force) throws FHIRPersistenceException { final String METHODNAME = "reindex"; log.entering(CLASSNAME, METHODNAME); @@ -2932,7 +2932,7 @@ public int reindex(FHIRPersistenceContext context, OperationOutcome.Builder oper * @throws Exception */ public void updateParameters(ResourceIndexRecord rir, Class resourceTypeClass, org.linuxforhealth.fhir.persistence.jdbc.dto.Resource existingResourceDTO, - ReindexResourceDAO reindexDAO, OperationOutcome.Builder operationOutcomeResult, boolean force) throws Exception { + ReindexResourceDAO reindexDAO, OperationOutcome.Builder operationOutcomeResult, boolean force) throws Exception { if (existingResourceDTO != null && !existingResourceDTO.isDeleted()) { T existingResource = this.convertResourceDTO(existingResourceDTO, resourceTypeClass, null); @@ -3016,7 +3016,7 @@ private void transactionCompleted(Boolean committed) { // because the transaction has commited, we can publish any ids generated // during parameter storage paramValueCollector.publishValuesToCache(); - + // See if we have any erase resources to clean up for (ErasedResourceRec err: this.eraseResourceRecs) { try { @@ -3084,18 +3084,18 @@ private IParamValueProcessor makeParamValueProcessor(Connection connection) thro final String schemaName = schemaNameSupplier.getSchemaForRequestContext(connection); final IParameterIdentityCache identityCache = new JDBCParameterCacheAdapter(this.cache); switch (this.connectionStrategy.getFlavor().getSchemaType()) { - case PLAIN: - if (this.connectionStrategy.getFlavor().getType() == DbType.DERBY) { - result = new PlainDerbyParamValueProcessor(connection, schemaName, identityCache); - } else { - result = new PlainPostgresParamValueProcessor(connection, schemaName, identityCache); - } - break; - case DISTRIBUTED: - result = new DistributedPostgresParamValueProcessor(connection, schemaName, identityCache); - break; - default: - throw new FHIRPersistenceException("Schema type not supported: " + connectionStrategy.getFlavor().getSchemaType().name()); + case PLAIN: + if (this.connectionStrategy.getFlavor().getType() == DbType.DERBY) { + result = new PlainDerbyParamValueProcessor(connection, schemaName, identityCache); + } else { + result = new PlainPostgresParamValueProcessor(connection, schemaName, identityCache); + } + break; + case DISTRIBUTED: + result = new DistributedPostgresParamValueProcessor(connection, schemaName, identityCache); + break; + default: + throw new FHIRPersistenceException("Schema type not supported: " + connectionStrategy.getFlavor().getSchemaType().name()); } return result; } @@ -3121,7 +3121,7 @@ public void beforeCommit() throws FHIRPersistenceException { */ private void flush() throws FHIRPersistenceException { try (Connection connection = openConnection(); - MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_FLUSH_TX_DATA.name())) { + MetricHandle mh = FHIRRequestContext.get().getMetricHandle(FHIRPersistenceJDBCMetric.M_JDBC_FLUSH_TX_DATA.name())) { IParamValueProcessor paramValueProcessor = makeParamValueProcessor(connection); try { // publish all the values collected in this transaction using the paramValueProcessor @@ -3205,7 +3205,7 @@ public void onCommit(Collection records, Collection resourceType, java.time.Instant fromLastModified, - java.time.Instant toLastModified, Function processor) throws FHIRPersistenceException { + java.time.Instant toLastModified, Function processor) throws FHIRPersistenceException { try (Connection connection = openConnection()) { doCachePrefill(null, connection); // translator is required to handle some simple SQL syntax differences. This is easier @@ -3229,7 +3229,7 @@ public ResourcePayload fetchResourcePayloads(Class resourceT @Override public List changes(FHIRPersistenceContext context, int resourceCount, java.time.Instant sinceLastModified, java.time.Instant beforeLastModified, - Long changeIdMarker, List resourceTypeNames, boolean excludeTransactionTimeoutWindow, HistorySortOrder historySortOrder) + Long changeIdMarker, List resourceTypeNames, boolean excludeTransactionTimeoutWindow, HistorySortOrder historySortOrder) throws FHIRPersistenceException { try (Connection connection = openConnection()) { doCachePrefill(context, connection); diff --git a/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainBatchParameterProcessor.java b/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainBatchParameterProcessor.java index eeb064ae694..306754657f8 100644 --- a/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainBatchParameterProcessor.java +++ b/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainBatchParameterProcessor.java @@ -333,7 +333,7 @@ public void process(String requestShard, String resourceType, String logicalId, try { PlainPostgresParameterBatch dao = getParameterBatchDao(resourceType); - dao.addReference(logicalResourceId, parameterNameValue.getParameterNameId(), refLogicalResourceId.getLogicalResourceId(), parameter.getRefVersionId()); + dao.addReference(logicalResourceId, parameterNameValue.getParameterNameId(), refLogicalResourceId.getLogicalResourceId(), parameter.getRefVersionId(),parameter.getCompositeId()); } catch (SQLException x) { throw new FHIRPersistenceException("Failed inserting security params for '" + resourceType + "'"); } diff --git a/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainPostgresParameterBatch.java b/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainPostgresParameterBatch.java index dc2065794d9..bde4bc637d6 100644 --- a/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainPostgresParameterBatch.java +++ b/fhir-persistence-params/src/main/java/org/linuxforhealth/fhir/persistence/params/database/PlainPostgresParameterBatch.java @@ -516,11 +516,11 @@ public void addSecurity(long logicalResourceId, long commonTokenValueId) throws * @param refLogicalResourceId * @param refVersionId */ - public void addReference(long logicalResourceId, int parameterNameId, long refLogicalResourceId, Integer refVersionId) throws SQLException { + public void addReference(long logicalResourceId, int parameterNameId, long refLogicalResourceId, Integer refVersionId,Integer compositeId) throws SQLException { logger.fine(() -> "Adding reference: parameterNameId:" + parameterNameId + " refLogicalResourceId:" + refLogicalResourceId + " refVersionId:" + refVersionId); if (refs == null) { final String tablePrefix = resourceType.toLowerCase(); - final String insertString = "INSERT INTO " + tablePrefix + "_ref_values (parameter_name_id, logical_resource_id, ref_logical_resource_id, ref_version_id) VALUES (?,?,?,?)"; + final String insertString = "INSERT INTO " + tablePrefix + "_ref_values (parameter_name_id, logical_resource_id, ref_logical_resource_id, ref_version_id,composite_id) VALUES (?,?,?,?,?)"; refs = connection.prepareStatement(insertString); } PreparedStatementHelper psh = new PreparedStatementHelper(refs); @@ -528,6 +528,7 @@ public void addReference(long logicalResourceId, int parameterNameId, long refLo .setLong(logicalResourceId) .setLong(refLogicalResourceId) .setInt(refVersionId) + .setInt(compositeId) .addBatch(); refCount++; } diff --git a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/FHIRHistoryContext.java b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/FHIRHistoryContext.java index 16c809b7aaf..2a92e1dddce 100644 --- a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/FHIRHistoryContext.java +++ b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/FHIRHistoryContext.java @@ -8,9 +8,15 @@ import org.linuxforhealth.fhir.core.context.FHIRPagingContext; import org.linuxforhealth.fhir.model.type.Instant; +import org.linuxforhealth.fhir.persistence.HistorySortOrder; public interface FHIRHistoryContext extends FHIRPagingContext { - + Instant getSince(); void setSince(Instant since); + + HistorySortOrder getHistorySortOrder(); + + void setHistorySortOrder(HistorySortOrder value); + } diff --git a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/impl/FHIRHistoryContextImpl.java b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/impl/FHIRHistoryContextImpl.java index 75f12cd024f..236bc3ca734 100644 --- a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/impl/FHIRHistoryContextImpl.java +++ b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/context/impl/FHIRHistoryContextImpl.java @@ -8,11 +8,17 @@ import org.linuxforhealth.fhir.core.context.impl.FHIRPagingContextImpl; import org.linuxforhealth.fhir.model.type.Instant; +import org.linuxforhealth.fhir.persistence.HistorySortOrder; import org.linuxforhealth.fhir.persistence.context.FHIRHistoryContext; +import org.linuxforhealth.fhir.search.parameters.QueryParameter; +import org.linuxforhealth.fhir.search.parameters.SortParameter; + +import java.util.List; public class FHIRHistoryContextImpl extends FHIRPagingContextImpl implements FHIRHistoryContext { private Instant since = null; - + private HistorySortOrder historySortOrder = null; + public FHIRHistoryContextImpl() { } @@ -25,4 +31,16 @@ public Instant getSince() { public void setSince(Instant since) { this.since = since; } + + @Override + public HistorySortOrder getHistorySortOrder() { + return historySortOrder; + } + + @Override + public void setHistorySortOrder(HistorySortOrder value) { + historySortOrder = value; + } + + } diff --git a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/util/FHIRPersistenceUtil.java b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/util/FHIRPersistenceUtil.java index 4a8515e211c..374ff3fd65f 100644 --- a/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/util/FHIRPersistenceUtil.java +++ b/fhir-persistence/src/main/java/org/linuxforhealth/fhir/persistence/util/FHIRPersistenceUtil.java @@ -67,11 +67,14 @@ public static FHIRHistoryContext parseHistoryParameters(Map if (!dt.isPartial()) { Instant since = Instant.of(ZonedDateTime.from(dt.getValue())); context.setSince(since); - } - else { + } else { throw new FHIRPersistenceException("The '_since' parameter must be a fully specified ISO 8601 date/time"); } - } else if ("_format".equals(name)) { + }else if ("_sort".equals(name)) { + HistorySortOrder sortOrder= getHistorySortOrder(first); + context.setHistorySortOrder(sortOrder); + } + else if ("_format".equals(name)) { // safely ignore continue; } else { @@ -98,7 +101,7 @@ public static FHIRHistoryContext parseHistoryParameters(Map * @throws FHIRPersistenceException */ public static FHIRSystemHistoryContext parseSystemHistoryParameters(Map> queryParameters, boolean lenient, - ResourcesConfigAdapter resourcesConfig) throws FHIRPersistenceException { + ResourcesConfigAdapter resourcesConfig) throws FHIRPersistenceException { log.entering(FHIRPersistenceUtil.class.getName(), "parseSystemHistoryParameters"); FHIRSystemHistoryContextImpl context = new FHIRSystemHistoryContextImpl(); context.setLenient(lenient); @@ -160,16 +163,8 @@ public static FHIRSystemHistoryContext parseSystemHistoryParameters(Map