001/*-
002 * #%L
003 * HAPI FHIR Storage api
004 * %%
005 * Copyright (C) 2014 - 2025 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.bulk.export.svc;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.context.RuntimeResourceDefinition;
024import ca.uhn.fhir.jpa.bulk.export.model.ExportPIDIteratorParameters;
025import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
026import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
027import ca.uhn.fhir.rest.param.DateRangeParam;
028import org.hl7.fhir.instance.model.api.IIdType;
029import org.slf4j.Logger;
030import org.springframework.beans.factory.annotation.Autowired;
031
032import java.util.Collections;
033import java.util.Date;
034import java.util.List;
035import java.util.stream.Collectors;
036
037import static org.slf4j.LoggerFactory.getLogger;
038
039public class BulkExportHelperService {
040        private static final Logger ourLog = getLogger(BulkExportHelperService.class);
041
042        @Autowired
043        private MatchUrlService myMatchUrlService;
044
045        @Autowired
046        private FhirContext myContext;
047
048        public BulkExportHelperService() {}
049
050        /**
051         * Given the parameters, create the search parameter map based on type filters and the _since parameter.
052         *
053         * The input boolean theConsiderDateRange determines whether to consider the lastUpdated date in the search parameter map.
054         */
055        public List<SearchParameterMap> createSearchParameterMapsForResourceType(
056                        RuntimeResourceDefinition theDef, ExportPIDIteratorParameters theParams, boolean theConsiderDateRange) {
057                String resourceType = theDef.getName();
058                List<String> typeFilters = theParams.getFilters();
059                List<SearchParameterMap> spMaps = null;
060                spMaps = typeFilters.stream()
061                                .filter(typeFilter -> typeFilter.startsWith(resourceType + "?"))
062                                .map(filter -> buildSearchParameterMapForTypeFilter(
063                                                filter, theDef, theParams.getStartDate(), theParams.getEndDate()))
064                                .collect(Collectors.toList());
065
066                typeFilters.stream().filter(filter -> !filter.contains("?")).forEach(filter -> {
067                        ourLog.warn(
068                                        "Found a strange _typeFilter that we could not process: {}. _typeFilters should follow the format ResourceType?searchparameter=value .",
069                                        filter);
070                });
071
072                // None of the _typeFilters applied to the current resource type, so just make a simple one.
073                if (spMaps.isEmpty()) {
074                        SearchParameterMap defaultMap = new SearchParameterMap();
075                        if (theConsiderDateRange) {
076                                addLastUpdatedFilter(defaultMap, theParams.getStartDate(), theParams.getEndDate());
077                        }
078                        spMaps = Collections.singletonList(defaultMap);
079                }
080
081                return spMaps;
082        }
083
084        private SearchParameterMap buildSearchParameterMapForTypeFilter(
085                        String theFilter, RuntimeResourceDefinition theDef, Date theStartDate, Date theEndDate) {
086                SearchParameterMap searchParameterMap = myMatchUrlService.translateMatchUrl(theFilter, theDef);
087                addLastUpdatedFilter(searchParameterMap, theStartDate, theEndDate);
088                return searchParameterMap;
089        }
090
091        void addLastUpdatedFilter(SearchParameterMap map, Date theStartDate, Date theEndDate) {
092                map.setLoadSynchronous(true);
093                if (theStartDate != null || theEndDate != null) {
094                        map.setLastUpdated(new DateRangeParam(theStartDate, theEndDate));
095                }
096        }
097
098        /**
099         * Converts the ResourceId to an IIdType.
100         * Eg: Patient/123 -> IIdType
101         * @param theResourceId - string version if the id
102         * @return - the IIdType
103         */
104        public IIdType toId(String theResourceId) {
105                IIdType retVal = myContext.getVersion().newIdType();
106                retVal.setValue(theResourceId);
107                return retVal;
108        }
109}