fhir_sdk/client/fhir/
operations.rs

1//! Implementation of certain FHIR operations.
2
3use fhir_model::for_all_versions;
4use reqwest::header;
5
6use super::{Client, Error};
7use crate::version::{FhirVersion, fhir_version};
8
9/// Implement the operation "Encounter/<id>/$everything" for the appropriate
10/// versions.
11macro_rules! impl_operation_encounter_everything {
12	($version:ident) => {
13		mod $version {
14			use fhir_model::$version::resources::Bundle;
15
16			use super::*;
17
18			/// Selected FHIR version.
19			type Version = fhir_version!($version);
20
21			impl Client<Version> {
22				/// Operation `$everything` on `Encounter`, returning a Bundle with all
23				/// resources for an `Encounter` record.
24				pub async fn operation_encounter_everything(
25					&self,
26					id: &str,
27				) -> Result<Bundle, Error> {
28					let url = self.url(&["Encounter", id, "$everything"]);
29					let request = self.0.client.get(url).header(header::ACCEPT, Version::MIME_TYPE);
30
31					let response = self.run_request(request).await?;
32					if response.status().is_success() {
33						let resource: Bundle = response.json().await?;
34						Ok(resource)
35					} else {
36						Err(Error::from_response::<Version>(response).await)
37					}
38				}
39			}
40		}
41	};
42}
43mod operation_1 {
44	//! Module for avoidance of conflicts.
45	use super::*;
46	for_all_versions!(impl_operation_encounter_everything);
47}
48
49/// Implement the operation "Patient/<id>/$everything" for the appropriate
50/// versions.
51macro_rules! impl_operation_patient_everything {
52	($version:ident) => {
53		mod $version {
54			use fhir_model::$version::resources::Bundle;
55
56			use super::*;
57
58			/// Selected FHIR version.
59			type Version = fhir_version!($version);
60
61			impl Client<Version> {
62				/// Operation `$everything` on `Patient`, returning a Bundle with all
63				/// resources for an `Patient` record.
64				pub async fn operation_patient_everything(
65					&self,
66					id: &str,
67				) -> Result<Bundle, Error> {
68					let url = self.url(&["Patient", id, "$everything"]);
69					let request = self.0.client.get(url).header(header::ACCEPT, Version::MIME_TYPE);
70
71					let response = self.run_request(request).await?;
72					if response.status().is_success() {
73						let resource: Bundle = response.json().await?;
74						Ok(resource)
75					} else {
76						Err(Error::from_response::<Version>(response).await)
77					}
78				}
79			}
80		}
81	};
82}
83mod operation_2 {
84	//! Module for avoidance of conflicts.
85	use super::*;
86	for_all_versions!(impl_operation_patient_everything);
87}
88
89/// Implement the operation "Patient/$match" for the appropriate versions.
90macro_rules! impl_operation_patient_match {
91	($version:ident) => {
92		mod $version {
93			use fhir_model::$version::resources::{
94				Bundle, Parameters, ParametersParameter, ParametersParameterValue, Patient,
95				Resource,
96			};
97
98			use super::*;
99
100			/// Selected FHIR version.
101			type Version = fhir_version!($version);
102
103			impl Client<Version> {
104				/// Operation `$match` on `Patient`, returning matches for Patient
105				/// records based on a given incomplete Patient resource.
106				pub async fn operation_patient_match(
107					&self,
108					patient: Patient,
109					only_certain: bool,
110					count: i32,
111				) -> Result<Bundle, Error> {
112					#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
113					let parameters = Parameters::builder()
114						.parameter(vec![
115							Some(
116								ParametersParameter::builder()
117									.name("resource".to_owned())
118									.resource(Resource::from(patient))
119									.build()
120									.unwrap(),
121							),
122							Some(
123								ParametersParameter::builder()
124									.name("onlyCertainMatches".to_owned())
125									.value(ParametersParameterValue::Boolean(only_certain))
126									.build()
127									.unwrap(),
128							),
129							Some(
130								ParametersParameter::builder()
131									.name("count".to_owned())
132									.value(ParametersParameterValue::Integer(count))
133									.build()
134									.unwrap(),
135							),
136						])
137						.build()
138						.unwrap();
139
140					let url = self.url(&["Patient", "$match"]);
141					let request = self
142						.0
143						.client
144						.post(url)
145						.header(header::ACCEPT, Version::MIME_TYPE)
146						.header(header::CONTENT_TYPE, Version::MIME_TYPE)
147						.json(&parameters);
148
149					let response = self.run_request(request).await?;
150					if response.status().is_success() {
151						let resource: Bundle = response.json().await?;
152						Ok(resource)
153					} else {
154						Err(Error::from_response::<Version>(response).await)
155					}
156				}
157			}
158		}
159	};
160}
161mod operation_3 {
162	//! Module for avoidance of conflicts.
163	use super::*;
164	for_all_versions!(impl_operation_patient_match);
165}
166
167/// Implement the operation "Subscription/<id>/$status" for the appropriate
168/// versions.
169macro_rules! impl_operation_subscription_status {
170	// These versions do not have that operation.
171	(stu3) => {};
172	(r4b) => {};
173	// Implement it for all others.
174	($version:ident) => {
175		mod $version {
176			use fhir_model::$version::resources::{Bundle, SubscriptionStatus};
177
178			use super::*;
179
180			/// Selected FHIR version.
181			type Version = fhir_version!($version);
182
183			impl Client<Version> {
184				/// Operation `$status` on `Subscription`, returning the
185				/// `SubcriptionStatus`.
186				pub async fn operation_subscription_status(
187					&self,
188					id: &str,
189				) -> Result<SubscriptionStatus, Error> {
190					let url = self.url(&["Subscription", id, "$status"]);
191					let request =
192						self.0.client.get(url.clone()).header(header::ACCEPT, Version::MIME_TYPE);
193
194					let response = self.run_request(request).await?;
195					if response.status().is_success() {
196						let bundle: Bundle = response.json().await?;
197						let resource = bundle
198							.0
199							.entry
200							.into_iter()
201							.flatten()
202							.filter_map(|entry| entry.resource)
203							.find_map(|res| SubscriptionStatus::try_from(res).ok())
204							.ok_or_else(|| Error::ResourceNotFound(url.to_string()))?;
205						Ok(resource)
206					} else {
207						Err(Error::from_response::<Version>(response).await)
208					}
209				}
210			}
211		}
212	};
213}
214mod operation_4 {
215	//! Module for avoidance of conflicts.
216	use super::*;
217	for_all_versions!(impl_operation_subscription_status);
218}
219
220/// Implement the operation "Subscription/<id>/$events" for the appropriate
221/// versions.
222macro_rules! impl_operation_subscription_events {
223	// These versions do not have that operation.
224	(stu3) => {};
225	(r4b) => {};
226	// Implement it for all others.
227	($version:ident) => {
228		mod $version {
229			use fhir_model::$version::{codes::SubscriptionPayloadContent, resources::Bundle};
230
231			use super::*;
232
233			/// Selected FHIR version.
234			type Version = fhir_version!($version);
235
236			impl Client<Version> {
237				/// Operation `$events` on `Subscription`, returning the previous
238				/// notifications that were triggered by a topic.
239				pub async fn operation_subscription_events(
240					&self,
241					id: &str,
242					events_since: Option<i64>,
243					events_until: Option<i64>,
244					content: Option<SubscriptionPayloadContent>,
245				) -> Result<Bundle, Error> {
246					let mut queries = Vec::new();
247					if let Some(events_since) = events_since {
248						queries.push(("eventsSinceNumber", events_since.to_string()));
249					}
250					if let Some(events_until) = events_until {
251						queries.push(("eventsUntilNumber", events_until.to_string()));
252					}
253					if let Some(content) = content {
254						queries.push(("content", content.to_string()));
255					}
256
257					let url = self.url(&["Subscription", id, "$events"]);
258					let request = self
259						.0
260						.client
261						.get(url)
262						.query(&queries)
263						.header(header::ACCEPT, Version::MIME_TYPE);
264
265					let response = self.run_request(request).await?;
266					if response.status().is_success() {
267						let bundle: Bundle = response.json().await?;
268						Ok(bundle)
269					} else {
270						Err(Error::from_response::<Version>(response).await)
271					}
272				}
273			}
274		}
275	};
276}
277mod operation_5 {
278	//! Module for avoidance of conflicts.
279	use super::*;
280	for_all_versions!(impl_operation_subscription_events);
281}