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.dao; 021 022import ca.uhn.fhir.i18n.Msg; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoPatient; 025import ca.uhn.fhir.jpa.api.dao.PatientEverythingParameters; 026import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc; 027import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; 028import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum; 029import ca.uhn.fhir.model.api.IResource; 030import ca.uhn.fhir.rest.api.CacheControlDirective; 031import ca.uhn.fhir.rest.api.Constants; 032import ca.uhn.fhir.rest.api.SortSpec; 033import ca.uhn.fhir.rest.api.server.IBundleProvider; 034import ca.uhn.fhir.rest.api.server.RequestDetails; 035import ca.uhn.fhir.rest.param.DateRangeParam; 036import ca.uhn.fhir.rest.param.StringAndListParam; 037import ca.uhn.fhir.rest.param.TokenOrListParam; 038import ca.uhn.fhir.rest.param.TokenParam; 039import org.hl7.fhir.instance.model.api.IBaseResource; 040import org.hl7.fhir.instance.model.api.IIdType; 041import org.hl7.fhir.instance.model.api.IPrimitiveType; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044import org.springframework.beans.factory.annotation.Autowired; 045import org.springframework.transaction.annotation.Propagation; 046import org.springframework.transaction.annotation.Transactional; 047 048import java.util.Arrays; 049import java.util.Collections; 050import javax.servlet.http.HttpServletRequest; 051 052public class JpaResourceDaoPatient<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> 053 implements IFhirResourceDaoPatient<T> { 054 055 private static final Logger ourLog = LoggerFactory.getLogger(JpaResourceDaoPatient.class); 056 057 @Autowired 058 private IRequestPartitionHelperSvc myPartitionHelperSvc; 059 060 private IBundleProvider doEverythingOperation( 061 TokenOrListParam theIds, 062 IPrimitiveType<Integer> theCount, 063 IPrimitiveType<Integer> theOffset, 064 DateRangeParam theLastUpdated, 065 SortSpec theSort, 066 StringAndListParam theContent, 067 StringAndListParam theNarrative, 068 StringAndListParam theFilter, 069 StringAndListParam theTypes, 070 RequestDetails theRequest) { 071 SearchParameterMap paramMap = new SearchParameterMap(); 072 if (theCount != null) { 073 paramMap.setCount(theCount.getValue()); 074 } 075 if (theOffset != null) { 076 throw new IllegalArgumentException( 077 Msg.code(1106) + "Everything operation does not support offset searching"); 078 } 079 if (theContent != null) { 080 paramMap.add(Constants.PARAM_CONTENT, theContent); 081 } 082 if (theNarrative != null) { 083 paramMap.add(Constants.PARAM_TEXT, theNarrative); 084 } 085 if (theTypes != null) { 086 paramMap.add(Constants.PARAM_TYPE, theTypes); 087 } else { 088 paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive())); 089 } 090 091 paramMap.setEverythingMode( 092 theIds != null && theIds.getValuesAsQueryTokens().size() == 1 093 ? EverythingModeEnum.PATIENT_INSTANCE 094 : EverythingModeEnum.PATIENT_TYPE); 095 paramMap.setSort(theSort); 096 paramMap.setLastUpdated(theLastUpdated); 097 if (theIds != null) { 098 if (theRequest.getParameters().containsKey("_mdm")) { 099 String[] paramVal = theRequest.getParameters().get("_mdm"); 100 if (Arrays.asList(paramVal).contains("true")) { 101 theIds.getValuesAsQueryTokens().forEach(param -> param.setMdmExpand(true)); 102 } 103 } 104 paramMap.add("_id", theIds); 105 } 106 107 if (!isPagingProviderDatabaseBacked(theRequest)) { 108 paramMap.setLoadSynchronous(true); 109 } 110 111 RequestPartitionId requestPartitionId = myPartitionHelperSvc.determineReadPartitionForRequestForSearchType( 112 theRequest, getResourceName(), paramMap, null); 113 114 adjustCount(theRequest, paramMap); 115 116 return mySearchCoordinatorSvc.registerSearch( 117 this, 118 paramMap, 119 getResourceName(), 120 new CacheControlDirective().parse(theRequest.getHeaders(Constants.HEADER_CACHE_CONTROL)), 121 theRequest, 122 requestPartitionId); 123 } 124 125 private void adjustCount(RequestDetails theRequest, SearchParameterMap theParamMap) { 126 if (theRequest.getServer() == null) { 127 return; 128 } 129 130 if (theParamMap.getCount() == null && theRequest.getServer().getDefaultPageSize() != null) { 131 theParamMap.setCount(theRequest.getServer().getDefaultPageSize()); 132 return; 133 } 134 135 Integer maxPageSize = theRequest.getServer().getMaximumPageSize(); 136 if (maxPageSize != null && theParamMap.getCount() > maxPageSize) { 137 ourLog.info( 138 "Reducing {} from {} to {} which is the maximum allowable page size.", 139 Constants.PARAM_COUNT, 140 theParamMap.getCount(), 141 maxPageSize); 142 theParamMap.setCount(maxPageSize); 143 } 144 } 145 146 @Override 147 @Transactional(propagation = Propagation.SUPPORTS) 148 public IBundleProvider patientInstanceEverything( 149 HttpServletRequest theServletRequest, 150 RequestDetails theRequestDetails, 151 PatientEverythingParameters theQueryParams, 152 IIdType theId) { 153 TokenOrListParam id = new TokenOrListParam().add(new TokenParam(theId.getIdPart())); 154 return doEverythingOperation( 155 id, 156 theQueryParams.getCount(), 157 theQueryParams.getOffset(), 158 theQueryParams.getLastUpdated(), 159 theQueryParams.getSort(), 160 theQueryParams.getContent(), 161 theQueryParams.getNarrative(), 162 theQueryParams.getFilter(), 163 theQueryParams.getTypes(), 164 theRequestDetails); 165 } 166 167 @Override 168 @Transactional(propagation = Propagation.SUPPORTS) 169 public IBundleProvider patientTypeEverything( 170 HttpServletRequest theServletRequest, 171 RequestDetails theRequestDetails, 172 PatientEverythingParameters theQueryParams, 173 TokenOrListParam theId) { 174 return doEverythingOperation( 175 theId, 176 theQueryParams.getCount(), 177 theQueryParams.getOffset(), 178 theQueryParams.getLastUpdated(), 179 theQueryParams.getSort(), 180 theQueryParams.getContent(), 181 theQueryParams.getNarrative(), 182 theQueryParams.getFilter(), 183 theQueryParams.getTypes(), 184 theRequestDetails); 185 } 186}