use std::borrow::Cow;
use hubuum_client_derive::ApiResource;
use crate::{
ApiError, FilterOperator, GroupPermissionsResult, Object, QueryFilter,
client::{
r#async::{
CursorRequest as AsyncCursorRequest, EmptyPostParams as AsyncEmptyPostParams,
GraphRequest as AsyncGraphRequest, Handle as AsyncHandle, QueryOp as AsyncQueryOp,
},
sync::{
CursorRequest as SyncCursorRequest, EmptyPostParams as SyncEmptyPostParams,
GraphRequest as SyncGraphRequest, Handle as SyncHandle, QueryOp as SyncQueryOp,
one_or_err,
},
},
endpoints::Endpoint,
types::HubuumDateTime,
};
use super::Namespace;
#[derive(Debug, Clone, serde::Serialize)]
struct NewClassRelationFromClassParams {
to_hubuum_class_id: i32,
}
#[allow(dead_code)]
#[derive(ApiResource)]
pub struct ClassResource {
#[api(read_only)]
pub id: i32,
pub name: String,
pub description: String,
#[api(as_id)]
pub namespace: Namespace,
#[api(optional)]
pub json_schema: serde_json::Value,
#[api(optional)]
pub validate_schema: bool,
#[api(read_only)]
pub created_at: HubuumDateTime,
#[api(read_only)]
pub updated_at: HubuumDateTime,
}
#[allow(dead_code)]
#[derive(ApiResource)]
pub struct ClassRelationResource {
#[api(read_only)]
pub id: i32,
pub from_hubuum_class_id: i32,
pub to_hubuum_class_id: i32,
#[api(read_only)]
pub created_at: HubuumDateTime,
#[api(read_only)]
pub updated_at: HubuumDateTime,
}
#[derive(Default, Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
pub struct ClassWithPath {
pub id: i32,
pub name: String,
pub namespace_id: i32,
pub description: String,
pub json_schema: serde_json::Value,
pub validate_schema: bool,
pub created_at: HubuumDateTime,
pub updated_at: HubuumDateTime,
pub path: Vec<i32>,
}
#[derive(Default, Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
pub struct RelatedClassGraph {
pub classes: Vec<ClassWithPath>,
pub relations: Vec<ClassRelation>,
}
impl SyncHandle<Class> {
pub fn objects_query(&self) -> SyncQueryOp<Object> {
self.client().objects(self.id()).query()
}
pub fn objects(&self) -> Result<Vec<SyncHandle<Object>>, ApiError> {
let raw: Vec<Object> = self.objects_query().list()?;
Ok(raw
.into_iter()
.map(|obj| SyncHandle::new(self.client().clone(), obj))
.collect())
}
pub fn object_by_name(&self, name: &str) -> Result<SyncHandle<Object>, ApiError> {
let url_params = vec![
(Cow::Borrowed("class_id"), self.id().to_string().into()),
(Cow::Borrowed("name"), name.to_string().into()),
];
let raw: Vec<Object> = self.client().get(
Object::default(),
url_params,
vec![QueryFilter {
key: "name".to_string(),
value: name.to_string(),
operator: FilterOperator::Equals { is_negated: false },
}],
)?;
let got = one_or_err(raw)?;
let resource: Object = got;
Ok(SyncHandle::new(self.client().clone(), resource))
}
pub fn delete(&self) -> Result<(), ApiError> {
let url_params = vec![(Cow::Borrowed("delete_id"), self.id().to_string().into())];
self.client()
.request_with_endpoint::<SyncEmptyPostParams, ()>(
reqwest::Method::DELETE,
&Endpoint::Classes,
url_params,
vec![],
SyncEmptyPostParams {},
)?;
Ok(())
}
pub fn permissions(&self) -> Result<Vec<GroupPermissionsResult>, ApiError> {
let url_params = vec![(Cow::Borrowed("class_id"), self.id().to_string().into())];
let res = self
.client()
.request_with_endpoint::<SyncEmptyPostParams, Vec<GroupPermissionsResult>>(
reqwest::Method::GET,
&Endpoint::ClassPermissions,
url_params,
vec![],
SyncEmptyPostParams {},
)?;
Ok(res.unwrap_or_default())
}
pub fn permissions_request(&self) -> SyncCursorRequest<GroupPermissionsResult> {
SyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassPermissions,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_classes(&self) -> SyncCursorRequest<ClassWithPath> {
SyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassRelatedClasses,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_relations(&self) -> SyncCursorRequest<ClassRelation> {
SyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassRelatedRelations,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_graph(&self) -> SyncGraphRequest<RelatedClassGraph> {
SyncGraphRequest::new(
self.client().clone(),
Endpoint::ClassRelatedGraph,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn relation(&self, relation_id: i32) -> Result<SyncHandle<ClassRelation>, ApiError> {
let relation = self
.client()
.request_with_endpoint::<SyncEmptyPostParams, ClassRelation>(
reqwest::Method::GET,
&Endpoint::ClassRelationsById,
vec![(Cow::Borrowed("relation_id"), relation_id.to_string().into())],
vec![],
SyncEmptyPostParams {},
)?
.ok_or(ApiError::EmptyResult(
"Class relation returned empty result".into(),
))?;
Ok(SyncHandle::new(self.client().clone(), relation))
}
pub fn create_relation(&self, to_class_id: i32) -> Result<ClassRelation, ApiError> {
self.client()
.request_with_endpoint::<NewClassRelationFromClassParams, ClassRelation>(
reqwest::Method::POST,
&Endpoint::ClassRelationsFromClass,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
vec![],
NewClassRelationFromClassParams {
to_hubuum_class_id: to_class_id,
},
)?
.ok_or(ApiError::EmptyResult(
"Creating class relation returned empty result".into(),
))
}
pub fn delete_relation(&self, relation_id: i32) -> Result<(), ApiError> {
self.client()
.request_with_endpoint::<SyncEmptyPostParams, ()>(
reqwest::Method::DELETE,
&Endpoint::ClassRelationFromClassById,
vec![
(Cow::Borrowed("class_id"), self.id().to_string().into()),
(Cow::Borrowed("relation_id"), relation_id.to_string().into()),
],
vec![],
SyncEmptyPostParams {},
)?;
Ok(())
}
}
impl AsyncHandle<Class> {
pub fn objects_query(&self) -> AsyncQueryOp<Object> {
self.client().objects(self.id()).query()
}
pub async fn objects(&self) -> Result<Vec<AsyncHandle<Object>>, ApiError> {
let raw: Vec<Object> = self.objects_query().list().await?;
Ok(raw
.into_iter()
.map(|obj| AsyncHandle::new(self.client().clone(), obj))
.collect())
}
pub async fn object_by_name(&self, name: &str) -> Result<AsyncHandle<Object>, ApiError> {
let resource = self
.client()
.objects(self.id())
.query()
.add_filter_equals("name", name)
.one()
.await?;
Ok(AsyncHandle::new(self.client().clone(), resource))
}
pub async fn delete(&self) -> Result<(), ApiError> {
self.client().classes().delete(self.id()).await
}
pub async fn permissions(&self) -> Result<Vec<GroupPermissionsResult>, ApiError> {
let url_params = vec![(Cow::Borrowed("class_id"), self.id().to_string().into())];
let res = self
.client()
.request_with_endpoint::<AsyncEmptyPostParams, Vec<GroupPermissionsResult>>(
reqwest::Method::GET,
&Endpoint::ClassPermissions,
url_params,
vec![],
AsyncEmptyPostParams {},
)
.await?;
Ok(res.unwrap_or_default())
}
pub fn permissions_request(&self) -> AsyncCursorRequest<GroupPermissionsResult> {
AsyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassPermissions,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_classes(&self) -> AsyncCursorRequest<ClassWithPath> {
AsyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassRelatedClasses,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_relations(&self) -> AsyncCursorRequest<ClassRelation> {
AsyncCursorRequest::new(
self.client().clone(),
Endpoint::ClassRelatedRelations,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub fn related_graph(&self) -> AsyncGraphRequest<RelatedClassGraph> {
AsyncGraphRequest::new(
self.client().clone(),
Endpoint::ClassRelatedGraph,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
)
}
pub async fn relation(&self, relation_id: i32) -> Result<AsyncHandle<ClassRelation>, ApiError> {
let relation = self
.client()
.request_with_endpoint::<AsyncEmptyPostParams, ClassRelation>(
reqwest::Method::GET,
&Endpoint::ClassRelationsById,
vec![(Cow::Borrowed("relation_id"), relation_id.to_string().into())],
vec![],
AsyncEmptyPostParams {},
)
.await?
.ok_or(ApiError::EmptyResult(
"Class relation returned empty result".into(),
))?;
Ok(AsyncHandle::new(self.client().clone(), relation))
}
pub async fn create_relation(&self, to_class_id: i32) -> Result<ClassRelation, ApiError> {
self.client()
.request_with_endpoint::<NewClassRelationFromClassParams, ClassRelation>(
reqwest::Method::POST,
&Endpoint::ClassRelationsFromClass,
vec![(Cow::Borrowed("class_id"), self.id().to_string().into())],
vec![],
NewClassRelationFromClassParams {
to_hubuum_class_id: to_class_id,
},
)
.await?
.ok_or(ApiError::EmptyResult(
"Creating class relation returned empty result".into(),
))
}
pub async fn delete_relation(&self, relation_id: i32) -> Result<(), ApiError> {
self.client()
.request_with_endpoint::<AsyncEmptyPostParams, ()>(
reqwest::Method::DELETE,
&Endpoint::ClassRelationFromClassById,
vec![
(Cow::Borrowed("class_id"), self.id().to_string().into()),
(Cow::Borrowed("relation_id"), relation_id.to_string().into()),
],
vec![],
AsyncEmptyPostParams {},
)
.await?;
Ok(())
}
}