001/*-
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2023 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.search.reindex;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.context.RuntimeResourceDefinition;
024import ca.uhn.fhir.i18n.Msg;
025import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
026import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
027import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
028import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
029import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
030import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
031import ca.uhn.fhir.jpa.model.dao.JpaPid;
032import ca.uhn.fhir.jpa.model.entity.ForcedId;
033import ca.uhn.fhir.jpa.model.entity.ResourceTable;
034import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
035import org.hl7.fhir.instance.model.api.IBaseResource;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038import org.springframework.beans.factory.annotation.Autowired;
039import org.springframework.stereotype.Service;
040
041import static org.apache.commons.lang3.StringUtils.isBlank;
042
043/**
044 * @deprecated
045 */
046@Service
047public class ResourceReindexer {
048        private static final Logger ourLog = LoggerFactory.getLogger(ResourceReindexer.class);
049
050        @Autowired
051        private IResourceHistoryTableDao myResourceHistoryTableDao;
052
053        @Autowired
054        private IForcedIdDao myForcedIdDao;
055
056        @Autowired
057        private IResourceTableDao myResourceTableDao;
058
059        @Autowired
060        private DaoRegistry myDaoRegistry;
061
062        @Autowired(required = false)
063        private IFulltextSearchSvc myFulltextSearchSvc;
064
065        private final FhirContext myFhirContext;
066
067        public ResourceReindexer(FhirContext theFhirContext) {
068                myFhirContext = theFhirContext;
069        }
070
071        public void readAndReindexResourceByPid(Long theResourcePid) {
072                ResourceTable resourceTable =
073                                myResourceTableDao.findById(theResourcePid).orElseThrow(IllegalStateException::new);
074                reindexResourceEntity(resourceTable);
075        }
076
077        public void reindexResourceEntity(ResourceTable theResourceTable) {
078                /*
079                 * This part is because from HAPI 1.5 - 1.6 we changed the format of forced ID to be "type/id" instead of just "id"
080                 */
081                ForcedId forcedId = theResourceTable.getForcedId();
082                if (forcedId != null) {
083                        if (isBlank(forcedId.getResourceType())) {
084                                ourLog.info(
085                                                "Updating resource {} forcedId type to {}",
086                                                forcedId.getForcedId(),
087                                                theResourceTable.getResourceType());
088                                forcedId.setResourceType(theResourceTable.getResourceType());
089                                myForcedIdDao.save(forcedId);
090                        }
091                }
092
093                IFhirResourceDao<?> dao = myDaoRegistry.getResourceDao(theResourceTable.getResourceType());
094                long expectedVersion = theResourceTable.getVersion();
095                IBaseResource resource = dao.readByPid(JpaPid.fromId(theResourceTable.getId()), true);
096
097                if (resource == null) {
098                        throw new InternalErrorException(Msg.code(1171) + "Could not find resource version "
099                                        + theResourceTable.getIdDt().toUnqualified().getValue() + " in database");
100                }
101
102                Long actualVersion = resource.getIdElement().getVersionIdPartAsLong();
103                if (actualVersion < expectedVersion) {
104                        ourLog.warn(
105                                        "Resource {} version {} does not exist, renumbering version {}",
106                                        resource.getIdElement().toUnqualifiedVersionless().getValue(),
107                                        resource.getIdElement().getVersionIdPart(),
108                                        expectedVersion);
109                        myResourceHistoryTableDao.updateVersion(theResourceTable.getId(), actualVersion, expectedVersion);
110                }
111
112                doReindex(theResourceTable, resource);
113        }
114
115        @SuppressWarnings("unchecked")
116        <T extends IBaseResource> void doReindex(ResourceTable theResourceTable, T theResource) {
117                RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theResource.getClass());
118                Class<T> resourceClass = (Class<T>) resourceDefinition.getImplementingClass();
119                final IFhirResourceDao<T> dao = myDaoRegistry.getResourceDao(resourceClass);
120                dao.reindex(theResource, theResourceTable);
121                if (myFulltextSearchSvc != null && !myFulltextSearchSvc.isDisabled()) {
122                        // update the full-text index, if active.
123                        myFulltextSearchSvc.reindex(theResourceTable);
124                }
125        }
126}