
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(name = JpaConstants.OPERATION_EVERYTHING, canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", idempotent = true, bundleType = BundleTypeEnum.SEARCHSET) 057 public IBundleProvider patientInstanceEverything( 058 059 javax.servlet.http.HttpServletRequest theServletRequest, 060 061 @IdParam 062 IIdType theId, 063 064 @Description(shortDefinition = "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") 065 @OperationParam(name = Constants.PARAM_COUNT, typeName = "unsignedInt") 066 IPrimitiveType<Integer> theCount, 067 068 @Description(shortDefinition = "Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") 069 @OperationParam(name = Constants.PARAM_OFFSET, typeName = "unsignedInt") 070 IPrimitiveType<Integer> theOffset, 071 072 @Description(shortDefinition = "Only return resources which were last updated as specified by the given range") 073 @OperationParam(name = Constants.PARAM_LASTUPDATED, min = 0, max = 1) 074 DateRangeParam theLastUpdated, 075 076 @Description(shortDefinition = "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)") 077 @OperationParam(name = Constants.PARAM_CONTENT, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 078 List<IPrimitiveType<String>> theContent, 079 080 @Description(shortDefinition = "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)") 081 @OperationParam(name = Constants.PARAM_TEXT, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 082 List<IPrimitiveType<String>> theNarrative, 083 084 @Description(shortDefinition = "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)") 085 @OperationParam(name = Constants.PARAM_FILTER, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 086 List<IPrimitiveType<String>> theFilter, 087 088 @Description(shortDefinition = "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)") 089 @OperationParam(name = Constants.PARAM_TYPE, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 090 List<IPrimitiveType<String>> theTypes, 091 092 @Sort 093 SortSpec theSortSpec, 094 095 RequestDetails theRequestDetails 096 ) { 097 098 startRequest(theServletRequest); 099 try { 100 PatientEverythingParameters everythingParams = new PatientEverythingParameters(); 101 everythingParams.setCount(theCount); 102 everythingParams.setOffset(theOffset); 103 everythingParams.setLastUpdated(theLastUpdated); 104 everythingParams.setSort(theSortSpec); 105 everythingParams.setContent(toStringAndList(theContent)); 106 everythingParams.setNarrative(toStringAndList(theNarrative)); 107 everythingParams.setFilter(toStringAndList(theFilter)); 108 everythingParams.setTypes(toStringAndList(theTypes)); 109 110 return ((IFhirResourceDaoPatient<?>) getDao()).patientInstanceEverything(theServletRequest, theRequestDetails, everythingParams, theId); 111 } finally { 112 endRequest(theServletRequest); 113 } 114 } 115 116 /** 117 * /Patient/$everything 118 */ 119 @Operation(name = JpaConstants.OPERATION_EVERYTHING, canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", idempotent = true, bundleType = BundleTypeEnum.SEARCHSET) 120 public IBundleProvider patientTypeEverything( 121 122 javax.servlet.http.HttpServletRequest theServletRequest, 123 124 @Description(shortDefinition = "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") 125 @OperationParam(name = Constants.PARAM_COUNT, typeName = "unsignedInt") 126 IPrimitiveType<Integer> theCount, 127 128 @Description(shortDefinition = "Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") 129 @OperationParam(name = Constants.PARAM_OFFSET, typeName = "unsignedInt") 130 IPrimitiveType<Integer> theOffset, 131 132 @Description(shortDefinition = "Only return resources which were last updated as specified by the given range") 133 @OperationParam(name = Constants.PARAM_LASTUPDATED, min = 0, max = 1) 134 DateRangeParam theLastUpdated, 135 136 @Description(shortDefinition = "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)") 137 @OperationParam(name = Constants.PARAM_CONTENT, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 138 List<IPrimitiveType<String>> theContent, 139 140 @Description(shortDefinition = "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)") 141 @OperationParam(name = Constants.PARAM_TEXT, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 142 List<IPrimitiveType<String>> theNarrative, 143 144 @Description(shortDefinition = "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)") 145 @OperationParam(name = Constants.PARAM_FILTER, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 146 List<IPrimitiveType<String>> theFilter, 147 148 @Description(shortDefinition = "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)") 149 @OperationParam(name = Constants.PARAM_TYPE, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") 150 List<IPrimitiveType<String>> theTypes, 151 152 153 @Description(shortDefinition = "Filter the resources to return based on the patient ids provided.") 154 @OperationParam(name = Constants.PARAM_ID, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "id") 155 List<IIdType> theId, 156 157 @Sort 158 SortSpec theSortSpec, 159 160 RequestDetails theRequestDetails 161 ) { 162 163 startRequest(theServletRequest); 164 try { 165 PatientEverythingParameters everythingParams = new PatientEverythingParameters(); 166 everythingParams.setCount(theCount); 167 everythingParams.setOffset(theOffset); 168 everythingParams.setLastUpdated(theLastUpdated); 169 everythingParams.setSort(theSortSpec); 170 everythingParams.setContent(toStringAndList(theContent)); 171 everythingParams.setNarrative(toStringAndList(theNarrative)); 172 everythingParams.setFilter(toStringAndList(theFilter)); 173 everythingParams.setTypes(toStringAndList(theTypes)); 174 175 return ((IFhirResourceDaoPatient<?>) getDao()).patientTypeEverything(theServletRequest, theRequestDetails, everythingParams, toFlattenedPatientIdTokenParamList(theId)); 176 } finally { 177 endRequest(theServletRequest); 178 } 179 180 } 181 182 /** 183 * Given a list of string types, return only the ID portions of any parameters passed in. 184 */ 185 private TokenOrListParam toFlattenedPatientIdTokenParamList(List<IIdType> theId) { 186 TokenOrListParam retVal = new TokenOrListParam(); 187 if (theId != null) { 188 for (IIdType next : theId) { 189 if (isNotBlank(next.getValue())) { 190 String[] split = next.getValueAsString().split(","); 191 Arrays.stream(split).map(IdDt::new).forEach(id -> { 192 retVal.addOr(new TokenParam(id.getIdPart())); 193 }); 194 } 195 } 196 } 197 198 return retVal.getValuesAsQueryTokens().isEmpty() ? null: retVal; 199 } 200 201 private StringAndListParam toStringAndList(List<IPrimitiveType<String>> theNarrative) { 202 StringAndListParam retVal = new StringAndListParam(); 203 if (theNarrative != null) { 204 for (IPrimitiveType<String> next : theNarrative) { 205 if (isNotBlank(next.getValue())) { 206 retVal.addAnd(new StringOrListParam().addOr(new StringParam(next.getValue()))); 207 } 208 } 209 } 210 if (retVal.getValuesAsQueryTokens().isEmpty()) { 211 return null; 212 } 213 return retVal; 214 } 215 216}