001package ca.uhn.fhir.jpa.sp;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.jpa.api.config.DaoConfig;
024import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
025import ca.uhn.fhir.jpa.model.config.PartitionSettings;
026import ca.uhn.fhir.jpa.model.entity.ResourceTable;
027import ca.uhn.fhir.jpa.model.entity.SearchParamPresent;
028import ca.uhn.fhir.jpa.util.AddRemoveCount;
029import com.google.common.annotations.VisibleForTesting;
030import org.springframework.beans.factory.annotation.Autowired;
031import org.springframework.stereotype.Service;
032
033import java.util.ArrayList;
034import java.util.Collection;
035import java.util.HashMap;
036import java.util.List;
037import java.util.Map;
038import java.util.Map.Entry;
039
040@Service
041public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
042
043        @Autowired
044        private ISearchParamPresentDao mySearchParamPresentDao;
045
046        @Autowired
047        private PartitionSettings myPartitionSettings;
048        @Autowired
049        private DaoConfig myDaoConfig;
050
051        @VisibleForTesting
052        public void setDaoConfig(DaoConfig theDaoConfig) {
053                myDaoConfig = theDaoConfig;
054        }
055
056        @Override
057        public AddRemoveCount
058        updatePresence(ResourceTable theResource, Map<String, Boolean> theParamNameToPresence) {
059                AddRemoveCount retVal = new AddRemoveCount();
060                if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.DISABLED) {
061                        return retVal;
062                }
063
064                Map<String, Boolean> presenceMap = new HashMap<>(theParamNameToPresence);
065
066                // Find existing entries
067                Collection<SearchParamPresent> existing;
068                existing = mySearchParamPresentDao.findAllForResource(theResource);
069                Map<Long, SearchParamPresent> existingHashToPresence = new HashMap<>();
070                for (SearchParamPresent nextExistingEntity : existing) {
071                        existingHashToPresence.put(nextExistingEntity.getHashPresence(), nextExistingEntity);
072                }
073
074                // Find newly wanted set of entries
075                Map<Long, SearchParamPresent> newHashToPresence = new HashMap<>();
076                for (Entry<String, Boolean> next : presenceMap.entrySet()) {
077                        String paramName = next.getKey();
078
079                        SearchParamPresent present = new SearchParamPresent();
080                        present.setPartitionSettings(myPartitionSettings);
081                        present.setResource(theResource);
082                        present.setParamName(paramName);
083                        present.setPresent(next.getValue());
084                        present.setPartitionId(theResource.getPartitionId());
085                        present.calculateHashes();
086
087                        newHashToPresence.put(present.getHashPresence(), present);
088                }
089
090                // Delete any that should be deleted
091                List<SearchParamPresent> toDelete = new ArrayList<>();
092                for (Entry<Long, SearchParamPresent> nextEntry : existingHashToPresence.entrySet()) {
093                        if (newHashToPresence.containsKey(nextEntry.getKey()) == false) {
094                                toDelete.add(nextEntry.getValue());
095                        }
096                }
097                mySearchParamPresentDao.deleteAll(toDelete);
098                retVal.addToRemoveCount(toDelete.size());
099
100                // Add any that should be added
101                List<SearchParamPresent> toAdd = new ArrayList<>();
102                for (Entry<Long, SearchParamPresent> nextEntry : newHashToPresence.entrySet()) {
103                        if (existingHashToPresence.containsKey(nextEntry.getKey()) == false) {
104                                toAdd.add(nextEntry.getValue());
105                        }
106                }
107                mySearchParamPresentDao.saveAll(toAdd);
108                retVal.addToRemoveCount(toAdd.size());
109
110                return retVal;
111        }
112
113}