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.provider; 021 022import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoPatient; 023import ca.uhn.fhir.jpa.api.dao.PatientEverythingParameters; 024import ca.uhn.fhir.jpa.model.util.JpaConstants; 025import ca.uhn.fhir.model.api.annotation.Description; 026import ca.uhn.fhir.model.primitive.IdDt; 027import ca.uhn.fhir.model.valueset.BundleTypeEnum; 028import ca.uhn.fhir.rest.annotation.IdParam; 029import ca.uhn.fhir.rest.annotation.Operation; 030import ca.uhn.fhir.rest.annotation.OperationParam; 031import ca.uhn.fhir.rest.annotation.Sort; 032import ca.uhn.fhir.rest.api.Constants; 033import ca.uhn.fhir.rest.api.SortSpec; 034import ca.uhn.fhir.rest.api.server.IBundleProvider; 035import ca.uhn.fhir.rest.api.server.RequestDetails; 036import ca.uhn.fhir.rest.param.DateRangeParam; 037import ca.uhn.fhir.rest.param.StringAndListParam; 038import ca.uhn.fhir.rest.param.StringOrListParam; 039import ca.uhn.fhir.rest.param.StringParam; 040import ca.uhn.fhir.rest.param.TokenOrListParam; 041import ca.uhn.fhir.rest.param.TokenParam; 042import org.hl7.fhir.instance.model.api.IBaseResource; 043import org.hl7.fhir.instance.model.api.IIdType; 044import org.hl7.fhir.instance.model.api.IPrimitiveType; 045 046import java.util.Arrays; 047import java.util.List; 048 049import static org.apache.commons.lang3.StringUtils.isNotBlank; 050 051public abstract class BaseJpaResourceProviderPatient<T extends IBaseResource> extends BaseJpaResourceProvider<T> { 052 053 /** 054 * Patient/123/$everything 055 */ 056 @Operation( 057 name = JpaConstants.OPERATION_EVERYTHING, 058 canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", 059 idempotent = true, 060 bundleType = BundleTypeEnum.SEARCHSET) 061 public IBundleProvider patientInstanceEverything( 062 javax.servlet.http.HttpServletRequest theServletRequest, 063 @IdParam IIdType theId, 064 @Description( 065 shortDefinition = 066 "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") 067 @OperationParam(name = Constants.PARAM_COUNT, typeName = "unsignedInt") 068 IPrimitiveType<Integer> theCount, 069 @Description( 070 shortDefinition = 071 "Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") 072 @OperationParam(name = Constants.PARAM_OFFSET, typeName = "unsignedInt") 073 IPrimitiveType<Integer> theOffset, 074 @Description( 075 shortDefinition = 076 "Only return resources which were last updated as specified by the given range") 077 @OperationParam(name = Constants.PARAM_LASTUPDATED, min = 0, max = 1) 078 DateRangeParam theLastUpdated, 079 @Description( 080 shortDefinition = 081 "Filter the resources to return only resources matching the given _content filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 082 @OperationParam( 083 name = Constants.PARAM_CONTENT, 084 min = 0, 085 max = OperationParam.MAX_UNLIMITED, 086 typeName = "string") 087 List<IPrimitiveType<String>> theContent, 088 @Description( 089 shortDefinition = 090 "Filter the resources to return only resources matching the given _text filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 091 @OperationParam( 092 name = Constants.PARAM_TEXT, 093 min = 0, 094 max = OperationParam.MAX_UNLIMITED, 095 typeName = "string") 096 List<IPrimitiveType<String>> theNarrative, 097 @Description( 098 shortDefinition = 099 "Filter the resources to return only resources matching the given _filter filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 100 @OperationParam( 101 name = Constants.PARAM_FILTER, 102 min = 0, 103 max = OperationParam.MAX_UNLIMITED, 104 typeName = "string") 105 List<IPrimitiveType<String>> theFilter, 106 @Description( 107 shortDefinition = 108 "Filter the resources to return only resources matching the given _type filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 109 @OperationParam( 110 name = Constants.PARAM_TYPE, 111 min = 0, 112 max = OperationParam.MAX_UNLIMITED, 113 typeName = "string") 114 List<IPrimitiveType<String>> theTypes, 115 @Sort SortSpec theSortSpec, 116 RequestDetails theRequestDetails) { 117 118 startRequest(theServletRequest); 119 try { 120 PatientEverythingParameters everythingParams = new PatientEverythingParameters(); 121 everythingParams.setCount(theCount); 122 everythingParams.setOffset(theOffset); 123 everythingParams.setLastUpdated(theLastUpdated); 124 everythingParams.setSort(theSortSpec); 125 everythingParams.setContent(toStringAndList(theContent)); 126 everythingParams.setNarrative(toStringAndList(theNarrative)); 127 everythingParams.setFilter(toStringAndList(theFilter)); 128 everythingParams.setTypes(toStringAndList(theTypes)); 129 130 return ((IFhirResourceDaoPatient<?>) getDao()) 131 .patientInstanceEverything(theServletRequest, theRequestDetails, everythingParams, theId); 132 } finally { 133 endRequest(theServletRequest); 134 } 135 } 136 137 /** 138 * /Patient/$everything 139 */ 140 @Operation( 141 name = JpaConstants.OPERATION_EVERYTHING, 142 canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", 143 idempotent = true, 144 bundleType = BundleTypeEnum.SEARCHSET) 145 public IBundleProvider patientTypeEverything( 146 javax.servlet.http.HttpServletRequest theServletRequest, 147 @Description( 148 shortDefinition = 149 "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") 150 @OperationParam(name = Constants.PARAM_COUNT, typeName = "unsignedInt") 151 IPrimitiveType<Integer> theCount, 152 @Description( 153 shortDefinition = 154 "Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") 155 @OperationParam(name = Constants.PARAM_OFFSET, typeName = "unsignedInt") 156 IPrimitiveType<Integer> theOffset, 157 @Description( 158 shortDefinition = 159 "Only return resources which were last updated as specified by the given range") 160 @OperationParam(name = Constants.PARAM_LASTUPDATED, min = 0, max = 1) 161 DateRangeParam theLastUpdated, 162 @Description( 163 shortDefinition = 164 "Filter the resources to return only resources matching the given _content filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 165 @OperationParam( 166 name = Constants.PARAM_CONTENT, 167 min = 0, 168 max = OperationParam.MAX_UNLIMITED, 169 typeName = "string") 170 List<IPrimitiveType<String>> theContent, 171 @Description( 172 shortDefinition = 173 "Filter the resources to return only resources matching the given _text filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 174 @OperationParam( 175 name = Constants.PARAM_TEXT, 176 min = 0, 177 max = OperationParam.MAX_UNLIMITED, 178 typeName = "string") 179 List<IPrimitiveType<String>> theNarrative, 180 @Description( 181 shortDefinition = 182 "Filter the resources to return only resources matching the given _filter filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 183 @OperationParam( 184 name = Constants.PARAM_FILTER, 185 min = 0, 186 max = OperationParam.MAX_UNLIMITED, 187 typeName = "string") 188 List<IPrimitiveType<String>> theFilter, 189 @Description( 190 shortDefinition = 191 "Filter the resources to return only resources matching the given _type filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)") 192 @OperationParam( 193 name = Constants.PARAM_TYPE, 194 min = 0, 195 max = OperationParam.MAX_UNLIMITED, 196 typeName = "string") 197 List<IPrimitiveType<String>> theTypes, 198 @Description(shortDefinition = "Filter the resources to return based on the patient ids provided.") 199 @OperationParam( 200 name = Constants.PARAM_ID, 201 min = 0, 202 max = OperationParam.MAX_UNLIMITED, 203 typeName = "id") 204 List<IIdType> theId, 205 @Sort SortSpec theSortSpec, 206 RequestDetails theRequestDetails) { 207 208 startRequest(theServletRequest); 209 try { 210 PatientEverythingParameters everythingParams = new PatientEverythingParameters(); 211 everythingParams.setCount(theCount); 212 everythingParams.setOffset(theOffset); 213 everythingParams.setLastUpdated(theLastUpdated); 214 everythingParams.setSort(theSortSpec); 215 everythingParams.setContent(toStringAndList(theContent)); 216 everythingParams.setNarrative(toStringAndList(theNarrative)); 217 everythingParams.setFilter(toStringAndList(theFilter)); 218 everythingParams.setTypes(toStringAndList(theTypes)); 219 220 return ((IFhirResourceDaoPatient<?>) getDao()) 221 .patientTypeEverything( 222 theServletRequest, 223 theRequestDetails, 224 everythingParams, 225 toFlattenedPatientIdTokenParamList(theId)); 226 } finally { 227 endRequest(theServletRequest); 228 } 229 } 230 231 /** 232 * Given a list of string types, return only the ID portions of any parameters passed in. 233 */ 234 private TokenOrListParam toFlattenedPatientIdTokenParamList(List<IIdType> theId) { 235 TokenOrListParam retVal = new TokenOrListParam(); 236 if (theId != null) { 237 for (IIdType next : theId) { 238 if (isNotBlank(next.getValue())) { 239 String[] split = next.getValueAsString().split(","); 240 Arrays.stream(split).map(IdDt::new).forEach(id -> { 241 retVal.addOr(new TokenParam(id.getIdPart())); 242 }); 243 } 244 } 245 } 246 247 return retVal.getValuesAsQueryTokens().isEmpty() ? null : retVal; 248 } 249 250 private StringAndListParam toStringAndList(List<IPrimitiveType<String>> theNarrative) { 251 StringAndListParam retVal = new StringAndListParam(); 252 if (theNarrative != null) { 253 for (IPrimitiveType<String> next : theNarrative) { 254 if (isNotBlank(next.getValue())) { 255 retVal.addAnd(new StringOrListParam().addOr(new StringParam(next.getValue()))); 256 } 257 } 258 } 259 if (retVal.getValuesAsQueryTokens().isEmpty()) { 260 return null; 261 } 262 return retVal; 263 } 264}