Skip to main content

openleadr_client/
program.rs

1use crate::{
2    Client, ClientKind, EventClient, Filter, PaginationOptions, ProgramId, ProgramRequest,
3    Timeline,
4    error::{Error, Result},
5};
6use openleadr_wire::{
7    Program,
8    event::{EventInterval, EventRequest, Priority},
9};
10
11/// A client for interacting with the data in a specific program and the events
12/// contained in the program.
13#[derive(Debug, Clone)]
14pub struct ProgramClient<K> {
15    client: Client<K>,
16    data: Program,
17}
18
19impl<K: ClientKind> ProgramClient<K> {
20    pub(super) fn from_program(client: Client<K>, program: Program) -> Self {
21        Self {
22            client,
23            data: program,
24        }
25    }
26
27    /// Get the id of the program
28    pub fn id(&self) -> &ProgramId {
29        &self.data.id
30    }
31
32    /// Get the time the program was created on the VTN
33    pub fn created_date_time(&self) -> chrono::DateTime<chrono::Utc> {
34        self.data.created_date_time
35    }
36
37    /// Get the time the program was last modified on the VTN
38    pub fn modification_date_time(&self) -> chrono::DateTime<chrono::Utc> {
39        self.data.modification_date_time
40    }
41
42    /// Read the data of the program
43    pub fn content(&self) -> &ProgramRequest {
44        &self.data.content
45    }
46
47    /// Modify the data of the program.
48    /// Make sure to call [`update`](Self::update)
49    /// after your modifications to store them on the VTN
50    pub fn content_mut(&mut self) -> &mut ProgramRequest {
51        &mut self.data.content
52    }
53
54    /// Stores any modifications made to the program content at the server
55    /// and refreshes the locally stored data with the returned VTN data
56    pub async fn update(&mut self) -> Result<()> {
57        self.data = self
58            .client
59            .client_ref
60            .put(&format!("programs/{}", self.id()), &self.data.content)
61            .await?;
62        Ok(())
63    }
64
65    /// Delete the program from the VTN
66    pub async fn delete(self) -> Result<Program> {
67        self.client
68            .client_ref
69            .delete(&format!("programs/{}", self.id()))
70            .await
71    }
72
73    /// Create a new event on the VTN.
74    /// The content should be created with [`ProgramClient::new_event`]
75    /// to automatically insert the correct program ID
76    pub async fn create_event(&self, event_data: EventRequest) -> Result<EventClient<K>> {
77        if &event_data.program_id != self.id() {
78            return Err(Error::InvalidParentObject);
79        }
80        let event = self.client.client_ref.post("events", &event_data).await?;
81        Ok(EventClient::from_event(
82            self.client.client_ref.clone(),
83            event,
84        ))
85    }
86
87    /// Create a new event object within the program
88    pub fn new_event(&self, intervals: Vec<EventInterval>) -> EventRequest {
89        EventRequest {
90            program_id: self.id().clone(),
91            event_name: None,
92            priority: Priority::UNSPECIFIED,
93            targets: vec![],
94            report_descriptors: None,
95            payload_descriptors: None,
96            interval_period: None,
97            duration: None,
98            intervals: Some(intervals),
99        }
100    }
101
102    /// Low-level operation that gets a list of events for this program from the VTN
103    /// with the given query parameters.
104    ///
105    /// To automatically iterate pages, use [`self.get_event_list`](Self::get_event_list)
106    pub async fn get_events_request(
107        &self,
108        filter: Filter<'_, impl AsRef<str>>,
109        pagination: PaginationOptions,
110    ) -> Result<Vec<EventClient<K>>> {
111        self.client
112            .get_events(Some(self.id()), filter, pagination)
113            .await
114    }
115
116    /// Get a list of events from the VTN with the given query parameters
117    pub async fn get_event_list(
118        &self,
119        filter: Filter<'_, impl AsRef<str> + Clone>,
120    ) -> Result<Vec<EventClient<K>>> {
121        self.client.get_event_list(Some(self.id()), filter).await
122    }
123
124    /// Retrieves the events for this program from the VTN and tries to build a [`Timeline`] from it.
125    pub async fn get_timeline(
126        &self,
127        filter: Filter<'_, impl AsRef<str> + Clone>,
128    ) -> Result<Timeline> {
129        let events = self.get_event_list(filter).await?;
130        let events = events.iter().map(|e| e.content()).collect();
131        Timeline::from_events(&self.data, events).ok_or(Error::InvalidInterval)
132    }
133}