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