Skip to main content

oxinat_core/protocols/
delete.rs

1use async_trait::async_trait;
2
3use crate::uri::data::resources::ResourcesUriBuilder;
4use crate::UriBuilder;
5use crate::client::{Xnat, ClientCore, ClientREST};
6use crate::models::{Experiment, Project, Resource, Scan, Subject};
7use crate::uri::data::{ExperimentUri, ProjectUriLegacy, SubjectUriLegacy};
8use crate::version::Version;
9use super::crud::{CrudError, Delete};
10
11/// Takes the `Option` value for the specified
12/// attribute, returning a `Result`. Otherwise
13/// fails and returns a
14/// `CrudError::IdentifierRequired`.
15macro_rules! acquire_identifier {
16    ($attr:expr, $error:literal) => {
17        $attr.take().ok_or(CrudError::IdentifierRequired($error.to_string()))
18    };
19}
20
21#[async_trait(?Send)]
22impl<V> Delete<Project> for Xnat<V>
23where
24    Self: ClientCore<Version = V> + ClientREST,
25    V: Version + ProjectUriLegacy,
26{
27    async fn delete_once(&self, model: Project) -> anyhow::Result<Project> {
28        let mut model_clone = model.clone();
29        let project = acquire_identifier!(model_clone.id, "project id")?;
30
31        self.delete(&self.version().project_data().with_id(project))
32            .await?
33            .send()
34            .await?;
35        Ok(model)
36    }
37}
38
39#[async_trait(?Send)]
40impl<V> Delete<Subject> for Xnat<V>
41where
42    Self: ClientCore<Version = V> + ClientREST,
43    V: Version + ProjectUriLegacy + SubjectUriLegacy,
44{
45    async fn delete_once(&self, model: Subject) -> anyhow::Result<Subject> {
46        let mut model_clone = model.clone();
47        let project = acquire_identifier!(model_clone.project, "project id")?;
48        let subject = acquire_identifier!(
49            model_clone
50                .label
51                .as_ref()
52                .or(model_clone.id.as_ref()),
53            "subject id")?;
54
55        let uri = self.version()
56            .project_data()
57            .with_id(project)
58            .subjects()
59            .with_subject(subject);
60        self.delete(&uri).await?.send().await?;
61        Ok(model)
62    }
63}
64
65#[async_trait(?Send)]
66impl<V> Delete<Experiment> for Xnat<V>
67where
68    Self: ClientCore<Version = V> + ClientREST,
69    V: Version + ExperimentUri + ProjectUriLegacy + SubjectUriLegacy,
70{
71    async fn delete_once(&self, model: Experiment) -> anyhow::Result<Experiment> {
72        let model_clone = model.clone();
73        let project = acquire_identifier!(
74            model_clone
75                .project
76                .as_ref()
77                .or(model_clone.subject_project.as_ref()),
78            "project id")?;
79        let subject = acquire_identifier!(
80            model_clone
81                .subject_label
82                .as_ref()
83                .or(model_clone.subject_id.as_ref()),
84            "subject id")?;
85        let session = acquire_identifier!(
86            model_clone
87                .id
88                .as_ref()
89                .or(model_clone.label.as_ref()),
90            "experiment id")?;
91
92        let uri = self.version()
93            .project_data()
94            .with_id(project)
95            .subjects()
96            .with_subject(subject)
97            .experiments()
98            .with_experiment(session);
99        self.delete(&uri).await?.send().await?;
100        Ok(model)
101    }
102}
103
104#[async_trait(?Send)]
105impl<V> Delete<Scan> for Xnat<V>
106where
107    Self: ClientCore<Version = V> + ClientREST,
108    V: Version + ExperimentUri + ProjectUriLegacy + SubjectUriLegacy,
109{
110    async fn delete_once(&self, model: Scan) -> anyhow::Result<Scan> {
111        let mut model_clone = model.clone();
112
113        let project = acquire_identifier!(
114            model_clone.project,
115            "project id")?;
116        let subject = acquire_identifier!(
117            model_clone.subject,
118            "subject id")?;
119        let session = acquire_identifier!(
120            model_clone.experiment,
121            "experiment id")?;
122        let scan = acquire_identifier!(model_clone.id, "scan id")?;
123
124        let uri = self.version()
125            .project_data()
126            .with_id(project)
127            .subjects()
128            .with_subject(subject)
129            .experiments()
130            .with_experiment(session);
131        self.delete(&uri.scans().with_scan(scan)).await?.send().await?;
132        Ok(model)
133    }
134}
135
136#[async_trait(?Send)]
137impl<V> Delete<Resource> for Xnat<V>
138where
139    Self: ClientCore<Version = V> + ClientREST,
140    V: Version + ExperimentUri + ProjectUriLegacy + SubjectUriLegacy,
141{
142    async fn delete_once(&self, model: Resource) -> anyhow::Result<Resource> {
143        let uri = match &model {
144            Resource {
145                project: Some(pjt),
146                subject: Some(sbj),
147                experiment: Some(exp),
148                scan: Some(scn),
149                ..
150            } => {
151                self
152                    .version()
153                    .project_data()
154                    .with_id(pjt)
155                    .subjects()
156                    .with_subject(sbj)
157                    .experiments()
158                    .with_experiment(exp)
159                    .scans()
160                    .with_scan(scn)
161                    .build()
162            },
163            Resource {
164                project: Some(pjt),
165                subject: Some(sbj),
166                experiment: Some(exp),
167                ..
168            } => {
169                self
170                    .version()
171                    .project_data()
172                    .with_id(pjt)
173                    .subjects()
174                    .with_subject(sbj)
175                    .experiments()
176                    .with_experiment(exp)
177                    .build()
178            },
179            Resource {
180                project: Some(pjt),
181                subject: Some(sbj),
182                ..
183            } => {
184                self
185                    .version()
186                    .project_data()
187                    .with_id(pjt)
188                    .subjects()
189                    .with_subject(sbj)
190                    .build()
191            },
192            Resource {
193                project: Some(pjt),
194                ..
195            } => {
196                self
197                    .version()
198                    .project_data()
199                    .with_id(pjt)
200                    .build()
201            },
202            _ => return Err(CrudError::IdentifierRequired("any identifiers".into()).into())
203        }?;
204        let uri = ResourcesUriBuilder::default().with_parent(&uri);
205        let uri = match &model {
206            Resource { collection: Some(c), name: Some(n), .. } => {
207                uri.with_resource(c).with_file(n)
208            },
209            Resource { collection: Some(c), .. } => {
210                uri.with_resource(c)
211            },
212            _ => uri,
213        };
214
215        self.delete(&uri).await?.send().await?;
216        Ok(model)
217    }
218}