View Javadoc
1   package ca.uhn.fhir.jpa.provider;
2   
3   import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
4   import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
5   import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
6   import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
7   import ca.uhn.fhir.jpa.util.JpaConstants;
8   import ca.uhn.fhir.model.api.annotation.Description;
9   import ca.uhn.fhir.model.dstu2.composite.MetaDt;
10  import ca.uhn.fhir.model.dstu2.resource.Bundle;
11  import ca.uhn.fhir.model.dstu2.resource.Parameters;
12  import ca.uhn.fhir.model.dstu2.resource.Parameters.Parameter;
13  import ca.uhn.fhir.model.primitive.BooleanDt;
14  import ca.uhn.fhir.model.primitive.DecimalDt;
15  import ca.uhn.fhir.model.primitive.IntegerDt;
16  import ca.uhn.fhir.model.primitive.StringDt;
17  import ca.uhn.fhir.rest.annotation.*;
18  import ca.uhn.fhir.rest.api.server.RequestDetails;
19  import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
20  import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
21  import org.hl7.fhir.instance.model.api.IIdType;
22  import org.hl7.fhir.r4.model.IntegerType;
23  import org.springframework.beans.factory.annotation.Autowired;
24  import org.springframework.beans.factory.annotation.Qualifier;
25  
26  import java.util.Collections;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  import java.util.TreeMap;
31  
32  import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
33  import static org.apache.commons.lang3.StringUtils.isBlank;
34  
35  /*
36   * #%L
37   * HAPI FHIR JPA Server
38   * %%
39   * Copyright (C) 2014 - 2018 University Health Network
40   * %%
41   * Licensed under the Apache License, Version 2.0 (the "License");
42   * you may not use this file except in compliance with the License.
43   * You may obtain a copy of the License at
44   * 
45   *      http://www.apache.org/licenses/LICENSE-2.0
46   * 
47   * Unless required by applicable law or agreed to in writing, software
48   * distributed under the License is distributed on an "AS IS" BASIS,
49   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50   * See the License for the specific language governing permissions and
51   * limitations under the License.
52   * #L%
53   */
54  
55  public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundle, MetaDt> {
56  
57  	@Autowired()
58  	@Qualifier("mySystemDaoDstu2")
59  	private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
60  
61  	@Autowired(required = false)
62  	private IFulltextSearchSvc mySearchDao;
63  
64  	@Operation(name = JpaConstants.OPERATION_EXPUNGE, idempotent = false, returnParameters = {
65  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerDt.class)
66  	})
67  	public Parameters expunge(
68  		@IdParam IIdType theIdParam,
69  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerDt theLimit,
70  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanDt theExpungeDeletedResources,
71  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanDt theExpungeOldVersions,
72  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_EVERYTHING) BooleanDt theExpungeEverything
73  	) {
74  		org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theLimit, theExpungeDeletedResources, theExpungeOldVersions, theExpungeEverything);
75  		return toExpungeResponse(retVal);
76  	}
77  
78  	@Operation(name = JpaConstants.OPERATION_EXPUNGE, idempotent = false, returnParameters = {
79  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerDt.class)
80  	})
81  	public Parameters expunge(
82  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerDt theLimit,
83  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanDt theExpungeDeletedResources,
84  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanDt theExpungeOldVersions,
85  		@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_EVERYTHING) BooleanDt theExpungeEverything
86  	) {
87  		org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theLimit, theExpungeDeletedResources, theExpungeOldVersions, theExpungeEverything);
88  		return toExpungeResponse(retVal);
89  	}
90  
91  	//@formatter:off
92  	// This is generated by hand:
93  	// ls hapi-fhir-structures-dstu2/target/generated-sources/tinder/ca/uhn/fhir/model/dstu2/resource/ | sort | sed "s/.java//" | sed "s/^/@OperationParam(name=\"/" | sed "s/$/\", type=IntegerDt.class, min=0, max=1),/"
94  	@Operation(name = JpaConstants.OPERATION_GET_RESOURCE_COUNTS, idempotent = true, returnParameters = {
95  		@OperationParam(name = "AllergyIntolerance", type = IntegerDt.class, min = 0, max = 1),
96  		@OperationParam(name = "Appointment", type = IntegerDt.class, min = 0, max = 1),
97  		@OperationParam(name = "AppointmentResponse", type = IntegerDt.class, min = 0, max = 1),
98  		@OperationParam(name = "AuditEvent", type = IntegerDt.class, min = 0, max = 1),
99  		@OperationParam(name = "Basic", type = IntegerDt.class, min = 0, max = 1),
100 		@OperationParam(name = "Binary", type = IntegerDt.class, min = 0, max = 1),
101 		@OperationParam(name = "BodySite", type = IntegerDt.class, min = 0, max = 1),
102 		@OperationParam(name = "Bundle", type = IntegerDt.class, min = 0, max = 1),
103 		@OperationParam(name = "CarePlan", type = IntegerDt.class, min = 0, max = 1),
104 		@OperationParam(name = "CarePlan2", type = IntegerDt.class, min = 0, max = 1),
105 		@OperationParam(name = "Claim", type = IntegerDt.class, min = 0, max = 1),
106 		@OperationParam(name = "ClaimResponse", type = IntegerDt.class, min = 0, max = 1),
107 		@OperationParam(name = "ClinicalImpression", type = IntegerDt.class, min = 0, max = 1),
108 		@OperationParam(name = "Communication", type = IntegerDt.class, min = 0, max = 1),
109 		@OperationParam(name = "CommunicationRequest", type = IntegerDt.class, min = 0, max = 1),
110 		@OperationParam(name = "Composition", type = IntegerDt.class, min = 0, max = 1),
111 		@OperationParam(name = "ConceptMap", type = IntegerDt.class, min = 0, max = 1),
112 		@OperationParam(name = "Condition", type = IntegerDt.class, min = 0, max = 1),
113 		@OperationParam(name = "Conformance", type = IntegerDt.class, min = 0, max = 1),
114 		@OperationParam(name = "Contract", type = IntegerDt.class, min = 0, max = 1),
115 		@OperationParam(name = "Contraindication", type = IntegerDt.class, min = 0, max = 1),
116 		@OperationParam(name = "Coverage", type = IntegerDt.class, min = 0, max = 1),
117 		@OperationParam(name = "DataElement", type = IntegerDt.class, min = 0, max = 1),
118 		@OperationParam(name = "Device", type = IntegerDt.class, min = 0, max = 1),
119 		@OperationParam(name = "DeviceComponent", type = IntegerDt.class, min = 0, max = 1),
120 		@OperationParam(name = "DeviceMetric", type = IntegerDt.class, min = 0, max = 1),
121 		@OperationParam(name = "DeviceUseRequest", type = IntegerDt.class, min = 0, max = 1),
122 		@OperationParam(name = "DeviceUseStatement", type = IntegerDt.class, min = 0, max = 1),
123 		@OperationParam(name = "DiagnosticOrder", type = IntegerDt.class, min = 0, max = 1),
124 		@OperationParam(name = "DiagnosticReport", type = IntegerDt.class, min = 0, max = 1),
125 		@OperationParam(name = "DocumentManifest", type = IntegerDt.class, min = 0, max = 1),
126 		@OperationParam(name = "DocumentReference", type = IntegerDt.class, min = 0, max = 1),
127 		@OperationParam(name = "EligibilityRequest", type = IntegerDt.class, min = 0, max = 1),
128 		@OperationParam(name = "EligibilityResponse", type = IntegerDt.class, min = 0, max = 1),
129 		@OperationParam(name = "Encounter", type = IntegerDt.class, min = 0, max = 1),
130 		@OperationParam(name = "EnrollmentRequest", type = IntegerDt.class, min = 0, max = 1),
131 		@OperationParam(name = "EnrollmentResponse", type = IntegerDt.class, min = 0, max = 1),
132 		@OperationParam(name = "EpisodeOfCare", type = IntegerDt.class, min = 0, max = 1),
133 		@OperationParam(name = "ExplanationOfBenefit", type = IntegerDt.class, min = 0, max = 1),
134 		@OperationParam(name = "FamilyMemberHistory", type = IntegerDt.class, min = 0, max = 1),
135 		@OperationParam(name = "Flag", type = IntegerDt.class, min = 0, max = 1),
136 		@OperationParam(name = "Goal", type = IntegerDt.class, min = 0, max = 1),
137 		@OperationParam(name = "Group", type = IntegerDt.class, min = 0, max = 1),
138 		@OperationParam(name = "HealthcareService", type = IntegerDt.class, min = 0, max = 1),
139 		@OperationParam(name = "ImagingObjectSelection", type = IntegerDt.class, min = 0, max = 1),
140 		@OperationParam(name = "ImagingStudy", type = IntegerDt.class, min = 0, max = 1),
141 		@OperationParam(name = "Immunization", type = IntegerDt.class, min = 0, max = 1),
142 		@OperationParam(name = "ImmunizationRecommendation", type = IntegerDt.class, min = 0, max = 1),
143 		@OperationParam(name = "ListResource", type = IntegerDt.class, min = 0, max = 1),
144 		@OperationParam(name = "Location", type = IntegerDt.class, min = 0, max = 1),
145 		@OperationParam(name = "Media", type = IntegerDt.class, min = 0, max = 1),
146 		@OperationParam(name = "Medication", type = IntegerDt.class, min = 0, max = 1),
147 		@OperationParam(name = "MedicationAdministration", type = IntegerDt.class, min = 0, max = 1),
148 		@OperationParam(name = "MedicationDispense", type = IntegerDt.class, min = 0, max = 1),
149 		@OperationParam(name = "MedicationPrescription", type = IntegerDt.class, min = 0, max = 1),
150 		@OperationParam(name = "MedicationStatement", type = IntegerDt.class, min = 0, max = 1),
151 		@OperationParam(name = "MessageHeader", type = IntegerDt.class, min = 0, max = 1),
152 		@OperationParam(name = "NamingSystem", type = IntegerDt.class, min = 0, max = 1),
153 		@OperationParam(name = "NutritionOrder", type = IntegerDt.class, min = 0, max = 1),
154 		@OperationParam(name = "Observation", type = IntegerDt.class, min = 0, max = 1),
155 		@OperationParam(name = "OperationDefinition", type = IntegerDt.class, min = 0, max = 1),
156 		@OperationParam(name = "OperationOutcome", type = IntegerDt.class, min = 0, max = 1),
157 		@OperationParam(name = "Order", type = IntegerDt.class, min = 0, max = 1),
158 		@OperationParam(name = "OrderResponse", type = IntegerDt.class, min = 0, max = 1),
159 		@OperationParam(name = "Organization", type = IntegerDt.class, min = 0, max = 1),
160 		@OperationParam(name = "Parameters", type = IntegerDt.class, min = 0, max = 1),
161 		@OperationParam(name = "Patient", type = IntegerDt.class, min = 0, max = 1),
162 		@OperationParam(name = "PaymentNotice", type = IntegerDt.class, min = 0, max = 1),
163 		@OperationParam(name = "PaymentReconciliation", type = IntegerDt.class, min = 0, max = 1),
164 		@OperationParam(name = "Person", type = IntegerDt.class, min = 0, max = 1),
165 		@OperationParam(name = "Practitioner", type = IntegerDt.class, min = 0, max = 1),
166 		@OperationParam(name = "Procedure", type = IntegerDt.class, min = 0, max = 1),
167 		@OperationParam(name = "ProcedureRequest", type = IntegerDt.class, min = 0, max = 1),
168 		@OperationParam(name = "ProcessRequest", type = IntegerDt.class, min = 0, max = 1),
169 		@OperationParam(name = "ProcessResponse", type = IntegerDt.class, min = 0, max = 1),
170 		@OperationParam(name = "Provenance", type = IntegerDt.class, min = 0, max = 1),
171 		@OperationParam(name = "Questionnaire", type = IntegerDt.class, min = 0, max = 1),
172 		@OperationParam(name = "QuestionnaireAnswers", type = IntegerDt.class, min = 0, max = 1),
173 		@OperationParam(name = "ReferralRequest", type = IntegerDt.class, min = 0, max = 1),
174 		@OperationParam(name = "RelatedPerson", type = IntegerDt.class, min = 0, max = 1),
175 		@OperationParam(name = "RiskAssessment", type = IntegerDt.class, min = 0, max = 1),
176 		@OperationParam(name = "Schedule", type = IntegerDt.class, min = 0, max = 1),
177 		@OperationParam(name = "SearchParameter", type = IntegerDt.class, min = 0, max = 1),
178 		@OperationParam(name = "Slot", type = IntegerDt.class, min = 0, max = 1),
179 		@OperationParam(name = "Specimen", type = IntegerDt.class, min = 0, max = 1),
180 		@OperationParam(name = "StructureDefinition", type = IntegerDt.class, min = 0, max = 1),
181 		@OperationParam(name = "Subscription", type = IntegerDt.class, min = 0, max = 1),
182 		@OperationParam(name = "Substance", type = IntegerDt.class, min = 0, max = 1),
183 		@OperationParam(name = "Supply", type = IntegerDt.class, min = 0, max = 1),
184 		@OperationParam(name = "ValueSet", type = IntegerDt.class, min = 0, max = 1),
185 		@OperationParam(name = "VisionPrescription", type = IntegerDt.class, min = 0, max = 1)
186 	})
187 	@Description(shortDefinition = "Provides the number of resources currently stored on the server, broken down by resource type")
188 	//@formatter:on
189 	public Parameters getResourceCounts() {
190 		Parameters retVal = new Parameters();
191 
192 		Map<String, Long> counts = mySystemDao.getResourceCountsFromCache();
193 		counts = defaultIfNull(counts, Collections.emptyMap());
194 		counts = new TreeMap<>(counts);
195 		for (Entry<String, Long> nextEntry : counts.entrySet()) {
196 			retVal.addParameter().setName(new StringDt(nextEntry.getKey())).setValue(new IntegerDt(nextEntry.getValue().intValue()));
197 		}
198 
199 		return retVal;
200 	}
201 
202 	@Operation(name = JpaConstants.OPERATION_META, idempotent = true, returnParameters = {
203 		@OperationParam(name = "return", type = MetaDt.class)
204 	})
205 	public Parameters meta(RequestDetails theRequestDetails) {
206 		Parameters parameters = new Parameters();
207 		parameters.addParameter().setName("return").setValue(getDao().metaGetOperation(theRequestDetails));
208 		return parameters;
209 	}
210 
211 	@Operation(name = JpaConstants.OPERATION_SUGGEST_KEYWORDS, idempotent = true)
212 	public Parameters suggestKeywords(
213 		@OperationParam(name = "context", min = 1, max = 1) String theContext,
214 		@OperationParam(name = "searchParam", min = 1, max = 1) String theSearchParam,
215 		@OperationParam(name = "text", min = 1, max = 1) String theText
216 	) {
217 		JpaSystemProviderDstu3.validateFulltextSearchEnabled(mySearchDao);
218 
219 		if (isBlank(theContext)) {
220 			throw new InvalidRequestException("Parameter 'context' must be provided");
221 		}
222 		if (isBlank(theSearchParam)) {
223 			throw new InvalidRequestException("Parameter 'searchParam' must be provided");
224 		}
225 		if (isBlank(theText)) {
226 			throw new InvalidRequestException("Parameter 'text' must be provided");
227 		}
228 
229 		List<Suggestion> keywords = mySearchDao.suggestKeywords(theContext, theSearchParam, theText);
230 
231 		Parameters retVal = new Parameters();
232 		for (Suggestion next : keywords) {
233 			retVal.addParameter()
234 				.addPart(new Parameter().setName("keyword").setValue(new StringDt(next.getTerm())))
235 				.addPart(new Parameter().setName("score").setValue(new DecimalDt(next.getScore())));
236 		}
237 
238 		return retVal;
239 	}
240 
241 	@Transaction
242 	public Bundle transaction(RequestDetails theRequestDetails, @TransactionParam Bundle theResources) {
243 		startRequest(((ServletRequestDetails) theRequestDetails).getServletRequest());
244 		try {
245 			return getDao().transaction(theRequestDetails, theResources);
246 		} finally {
247 			endRequest(((ServletRequestDetails) theRequestDetails).getServletRequest());
248 		}
249 	}
250 
251 	public static Parameters toExpungeResponse(org.hl7.fhir.r4.model.Parameters theRetVal) {
252 		Integer count = ((IntegerType) theRetVal.getParameterFirstRep().getValue()).getValue();
253 		return new Parameters()
254 			.addParameter(new Parameter().setName("count").setValue(new IntegerDt(count)));
255 	}
256 
257 }