use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::{
errors::{SuperSTACError, ValidationError},
utils::{get_date_time, parse_url, validate_identifier},
};
#[derive(Debug, Deserialize)]
pub struct CatalogProviderConfig {
pub id: String,
pub name: Option<String>,
pub description: Option<String>,
pub logo_url: Option<String>,
pub website_url: Option<String>,
pub stac_version: Option<String>,
pub catalog_ids: Option<Vec<String>>,
}
impl TryFrom<CatalogProviderConfig> for CatalogProvider {
type Error = SuperSTACError;
fn try_from(cfg: CatalogProviderConfig) -> Result<Self, Self::Error> {
validate_identifier(&cfg.id)?;
let website_url = match cfg.website_url {
Some(w) => {
parse_url(&w).map_err(|e| ValidationError::InvalidUrl(e.to_string()))?;
Some(w)
}
None => None,
};
let logo_url = match cfg.logo_url {
Some(l) => {
parse_url(&l).map_err(|e| ValidationError::InvalidUrl(e.to_string()))?;
Some(l)
}
None => None,
};
let stac_version = cfg
.stac_version
.ok_or_else(|| ValidationError::MissingField("stac_version".into()))?;
Ok(Self {
id: cfg.id,
name: cfg.name,
description: cfg.description,
website_url,
logo_url,
stac_version: Some(stac_version),
catalog_ids: None,
created_at: Some(get_date_time()),
updated_at: None,
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Default,PartialEq)]
pub struct CatalogProvider {
pub id: String,
pub name: Option<String>,
pub description: Option<String>,
pub logo_url: Option<String>,
pub stac_version: Option<String>,
pub website_url: Option<String>,
pub catalog_ids: Option<Vec<String>>,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
}
impl CatalogProvider {
pub fn new(
id: String,
name: Option<String>,
description: Option<String>,
website_url: Option<String>,
logo_url: Option<String>,
stac_version: Option<String>,
catalog_ids: Option<Vec<String>>,
) -> Result<Self, SuperSTACError> {
validate_identifier(&id)?;
let valid_website = if let Some(w) = website_url {
parse_url(w.as_str())
.map_err(|e| ValidationError::InvalidUrl(format!("Invalid website URL: {}", e)))?;
Some(w.to_string())
} else {
None
};
let valid_logo = if let Some(l) = logo_url {
parse_url(l.as_str())
.map_err(|e| ValidationError::InvalidUrl(format!("Invalid logo URL: {}", e)))?;
Some(l.to_string())
} else {
None
};
Ok(Self {
id,
name,
website_url: valid_website,
stac_version,
logo_url: valid_logo,
description,
catalog_ids,
created_at: Some(get_date_time()),
updated_at: None,
})
}
pub fn set_id(&mut self, id: String) {
self.id = id
}
pub fn update(
&mut self,
name: Option<String>,
website: Option<String>,
logo_url: Option<String>,
description: Option<String>,
stac_version: Option<String>,
catalog_ids: Option<Vec<String>>,
) -> Result<(), ValidationError> {
if let Some(updated_url) = logo_url {
match parse_url(&updated_url) {
Ok(valid_url) => {
self.logo_url = Some(valid_url.to_string());
}
Err(err) => {
return Err(ValidationError::InvalidUrl(err.to_string()));
}
}
}
if let Some(updated_url) = website {
match parse_url(&updated_url) {
Ok(valid_url) => {
self.website_url = Some(valid_url.to_string());
}
Err(err) => {
return Err(ValidationError::InvalidUrl(err.to_string()));
}
}
}
self.name = name;
self.description = description;
self.stac_version = stac_version;
self.catalog_ids = catalog_ids;
self.set_update_date();
Ok(())
}
pub fn set_update_date(&mut self) {
self.updated_at = Some(get_date_time());
}
pub fn set_created_date(&mut self) {
self.created_at = Some(get_date_time());
}
pub fn remove_catalog(&mut self, catalog_id: &str) {
if let Some(catalog_ids) = &mut self.catalog_ids {
catalog_ids.retain(|id| id != catalog_id);
if catalog_ids.is_empty() {
self.catalog_ids = None;
}
}
}
pub fn add_catalog(&mut self, catalog_id: &str) {
let catalog_ids = self.catalog_ids.get_or_insert_with(Vec::new);
if !catalog_ids.iter().any(|id| id == &catalog_id) {
catalog_ids.push(catalog_id.to_string());
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CatalogProviderFilters {
pub id: Option<String>,
pub name: Option<String>,
pub description: Option<String>,
pub stac_version: Option<String>,
pub catalog_id: Option<String>,
pub created_after: Option<DateTime<Utc>>,
pub created_before: Option<DateTime<Utc>>,
pub updated_after: Option<DateTime<Utc>>,
pub updated_before: Option<DateTime<Utc>>,
}
impl Default for CatalogProviderFilters {
fn default() -> Self {
CatalogProviderFilters{
id: None,
name:None,
stac_version:None,
catalog_id:None,
description: None,
created_after: None,
created_before: None,
updated_after: None,
updated_before: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CatalogProviderUpdate {
pub name: Option<String>,
pub description: Option<String>,
pub logo_url: Option<String>,
pub website_url: Option<String>,
pub stac_version: Option<String>,
pub catalog_ids: Option<Vec<String>>,
}