openleadr_client/
ven.rs

1use crate::{resource::ResourceClient, ClientRef, Error, Result};
2use chrono::{DateTime, Utc};
3use openleadr_wire::{
4    resource::{Resource, ResourceContent, ResourceId},
5    ven::{VenContent, VenId},
6    Ven,
7};
8use std::sync::Arc;
9
10/// A client for interacting with the data in a specific VEN and the resources contained in the VEN.
11#[derive(Debug, Clone)]
12pub struct VenClient {
13    client: Arc<ClientRef>,
14    data: Ven,
15}
16
17impl VenClient {
18    pub(super) fn from_ven(client: Arc<ClientRef>, data: Ven) -> Self {
19        Self { client, data }
20    }
21
22    /// Get the VEN ID
23    pub fn id(&self) -> &VenId {
24        &self.data.id
25    }
26
27    /// Get the time the VEN was created on the VTN
28    pub fn created_date_time(&self) -> DateTime<Utc> {
29        self.data.created_date_time
30    }
31
32    /// Get the time the VEN was last modified on the VTN
33    pub fn modification_date_time(&self) -> DateTime<Utc> {
34        self.data.modification_date_time
35    }
36
37    /// Read the content of the VEN
38    pub fn content(&self) -> &VenContent {
39        &self.data.content
40    }
41
42    /// Modify the content of the VEN.
43    /// Make sure to call [`update`](Self::update)
44    /// after your modifications to store them on the VTN.
45    pub fn content_mut(&mut self) -> &mut VenContent {
46        &mut self.data.content
47    }
48
49    /// Stores any modifications made to the VEN content at the VTN
50    /// and refreshes the data stored locally with the returned VTN data
51    pub async fn update(&mut self) -> Result<()> {
52        self.data = self
53            .client
54            .put(&format!("vens/{}", self.id()), &self.data.content)
55            .await?;
56        Ok(())
57    }
58
59    /// Delete the VEN from the VTN.
60    ///
61    /// Depending on the VTN implementation,
62    /// you may need to delete all associated resources before you can delete the VEN
63    pub async fn delete(self) -> Result<Ven> {
64        self.client.delete(&format!("vens/{}", self.id())).await
65    }
66
67    /// Create a resource as a child of this VEN
68    pub async fn create_resource(&self, resource: ResourceContent) -> Result<ResourceClient> {
69        let resource = self
70            .client
71            .post(&format!("vens/{}/resources", self.id()), &resource)
72            .await?;
73        Ok(ResourceClient::from_resource(
74            Arc::clone(&self.client),
75            self.id().clone(),
76            resource,
77        ))
78    }
79
80    async fn get_resources_req(
81        &self,
82        resource_name: Option<&str>,
83        skip: usize,
84        limit: usize,
85    ) -> Result<Vec<ResourceClient>> {
86        let skip_str = skip.to_string();
87        let limit_str = limit.to_string();
88
89        let mut query: Vec<(&str, &str)> = vec![("skip", &skip_str), ("limit", &limit_str)];
90
91        if let Some(resource_name) = resource_name {
92            query.push(("resourceName", resource_name));
93        }
94
95        let resources: Vec<Resource> = self
96            .client
97            .get(&format!("/vens/{}/resources", self.id()), &query)
98            .await?;
99        Ok(resources
100            .into_iter()
101            .map(|resource| {
102                ResourceClient::from_resource(Arc::clone(&self.client), self.id().clone(), resource)
103            })
104            .collect())
105    }
106
107    /// Get all resources stored as children of this VEN.
108    ///
109    /// The client automatically tries to iterate pages where necessary.
110    pub async fn get_all_resources(
111        &self,
112        resource_name: Option<&str>,
113    ) -> Result<Vec<ResourceClient>> {
114        self.client
115            .iterate_pages(|skip, limit| self.get_resources_req(resource_name, skip, limit))
116            .await
117    }
118
119    /// Get a resource by its ID
120    pub async fn get_resource_by_id(&self, id: &ResourceId) -> Result<ResourceClient> {
121        let resource = self
122            .client
123            .get(&format!("vens/{}/resources/{}", self.id(), id), &[])
124            .await?;
125        Ok(ResourceClient::from_resource(
126            Arc::clone(&self.client),
127            self.id().clone(),
128            resource,
129        ))
130    }
131
132    /// Get VEN by name from VTN.
133    /// According to the spec, a [`resource_name`](ResourceContent::resource_name) must be unique per VEN.
134    pub async fn get_resource_by_name(&self, name: &str) -> Result<ResourceClient> {
135        let mut resources: Vec<Resource> = self
136            .client
137            .get(
138                &format!("vens/{}/resources", self.id()),
139                &[("resourceName", name)],
140            )
141            .await?;
142        match resources[..] {
143            [] => Err(Error::ObjectNotFound),
144            [_] => Ok(ResourceClient::from_resource(
145                Arc::clone(&self.client),
146                self.id().clone(),
147                resources.remove(0),
148            )),
149            [..] => Err(Error::DuplicateObject),
150        }
151    }
152}