001/*
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2024 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.provider;
021
022import ca.uhn.fhir.i18n.Msg;
023import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
024import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
025import ca.uhn.fhir.jpa.term.api.ReindexTerminologyResult;
026import ca.uhn.fhir.rest.annotation.At;
027import ca.uhn.fhir.rest.annotation.History;
028import ca.uhn.fhir.rest.annotation.Offset;
029import ca.uhn.fhir.rest.annotation.Operation;
030import ca.uhn.fhir.rest.annotation.Since;
031import ca.uhn.fhir.rest.api.server.IBundleProvider;
032import ca.uhn.fhir.rest.api.server.RequestDetails;
033import ca.uhn.fhir.rest.param.DateRangeParam;
034import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
035import ca.uhn.fhir.rest.server.provider.ProviderConstants;
036import ca.uhn.fhir.util.ParametersUtil;
037import ca.uhn.fhir.util.StopWatch;
038import jakarta.servlet.http.HttpServletRequest;
039import org.apache.commons.lang3.exception.ExceptionUtils;
040import org.hl7.fhir.instance.model.api.IBaseParameters;
041import org.slf4j.Logger;
042import org.slf4j.LoggerFactory;
043import org.springframework.beans.factory.annotation.Autowired;
044
045import java.util.Date;
046
047public abstract class BaseJpaSystemProvider<T, MT> extends BaseStorageSystemProvider<T, MT>
048                implements IJpaSystemProvider {
049        private static final Logger ourLog = LoggerFactory.getLogger(BaseJpaSystemProvider.class);
050
051        public static final String RESP_PARAM_SUCCESS = "success";
052
053        /**
054         * @see ProviderConstants#OPERATION_REINDEX
055         * @deprecated
056         */
057        @Deprecated
058        public static final String MARK_ALL_RESOURCES_FOR_REINDEXING = ProviderConstants.MARK_ALL_RESOURCES_FOR_REINDEXING;
059        /**
060         * @see ProviderConstants#OPERATION_REINDEX
061         * @deprecated
062         */
063        @Deprecated
064        public static final String PERFORM_REINDEXING_PASS = ProviderConstants.PERFORM_REINDEXING_PASS;
065
066        @Autowired
067        private IResourceReindexingSvc myResourceReindexingSvc;
068
069        @Autowired
070        private ITermReadSvc myTermReadSvc;
071
072        public BaseJpaSystemProvider() {
073                // nothing
074        }
075
076        protected IResourceReindexingSvc getResourceReindexingSvc() {
077                return myResourceReindexingSvc;
078        }
079
080        @History
081        public IBundleProvider historyServer(
082                        HttpServletRequest theRequest,
083                        @Offset Integer theOffset,
084                        @Since Date theDate,
085                        @At DateRangeParam theAt,
086                        RequestDetails theRequestDetails) {
087                startRequest(theRequest);
088                try {
089                        DateRangeParam range = super.processSinceOrAt(theDate, theAt);
090                        return myDao.history(
091                                        range.getLowerBoundAsInstant(), range.getUpperBoundAsInstant(), theOffset, theRequestDetails);
092                } finally {
093                        endRequest(theRequest);
094                }
095        }
096
097        @Operation(name = ProviderConstants.OPERATION_REINDEX_TERMINOLOGY, idempotent = false)
098        public IBaseParameters reindexTerminology(RequestDetails theRequestDetails) {
099
100                ReindexTerminologyResult result;
101                StopWatch sw = new StopWatch();
102                try {
103                        result = myTermReadSvc.reindexTerminology();
104
105                } catch (Exception theE) {
106                        throw new InternalErrorException(
107                                        Msg.code(2072) + "Re-creating terminology freetext indexes failed with exception: "
108                                                        + theE.getMessage() + NL
109                                                        + "With trace:" + NL + ExceptionUtils.getStackTrace(theE));
110                }
111
112                IBaseParameters retVal = ParametersUtil.newInstance(getContext());
113                if (!result.equals(ReindexTerminologyResult.SUCCESS)) {
114                        ParametersUtil.addParameterToParametersBoolean(getContext(), retVal, RESP_PARAM_SUCCESS, false);
115                        String msg = result.equals(ReindexTerminologyResult.SEARCH_SVC_DISABLED)
116                                        ? "Freetext service is not configured. Operation didn't run."
117                                        : "Operation was cancelled because other terminology background tasks are currently running. Try again in a few minutes.";
118                        ParametersUtil.addParameterToParametersString(getContext(), retVal, "message", msg);
119                        return retVal;
120                }
121
122                ParametersUtil.addParameterToParametersBoolean(getContext(), retVal, RESP_PARAM_SUCCESS, true);
123                ourLog.info("Re-creating terminology freetext indexes took {}", sw);
124                return retVal;
125        }
126
127        public static final String NL = System.getProperty("line.separator");
128}