use std::net::SocketAddr;
use juiz_sdk::anyhow::anyhow;
use crate::prelude::*;
use super::super::core_broker::CoreBrokerPtr;
use super::crud_callback_container::{create_callback_container, delete_callback_container, read_callback_container, update_callback_container, ClassCallbackContainerType};
pub struct CRUDBroker {
core_broker: CoreBrokerPtr,
create_callback_container: ClassCallbackContainerType, read_callback_container: ClassCallbackContainerType, update_callback_container: ClassCallbackContainerType, delete_callback_container: ClassCallbackContainerType, }
fn _resource_name_to_cls_and_id<'a>(resource_name: &'a str, _params: &Vec<String>) -> JuizResult<(&'a str, Identifier)> {
let mut split = resource_name.split('/');
let class_name = split.next().ok_or( anyhow!(JuizError::CRUDBrokerGivenResourseNameHasNoClassNameError{resource_name: resource_name.to_string()} ))?;
Ok((class_name, "".to_string()))
}
impl CRUDBroker {
pub fn new(core_broker: CoreBrokerPtr) -> JuizResult<CRUDBroker> {
Ok(CRUDBroker{core_broker,
create_callback_container: create_callback_container(),
read_callback_container: read_callback_container(),
update_callback_container: update_callback_container(),
delete_callback_container: delete_callback_container()
})
}
fn on_update(&self, class_name:&str, function_name:&str, cp: CapsuleMap, opt_remote_addr: Option<SocketAddr>) -> JuizResult<CapsulePtr>{
log::trace!("on_update({cp:?}) called");
if class_name == "system" && function_name == "add_mastersystem" {
if let Some(remote_addr) = opt_remote_addr {
let remote_addr_str = remote_addr.to_string();
let _r = match cp.get("profile") {
Ok(capsule_ptr) => {
capsule_ptr.lock_modify_as_value(|v|{
match v.as_object_mut().unwrap().get_mut("subsystem").unwrap().as_object_mut() {
Some(obj) => {
let broker_name = obj.get("broker_name").unwrap().as_str().unwrap().to_owned();
let broker_tokens = broker_name.split(":").collect::<Vec<&str>>();
let port_str = broker_tokens.get(1).unwrap();
let remote_tokens = remote_addr_str.split(":").collect::<Vec<&str>>();
let addr_str = (*remote_tokens.get(0).unwrap()).to_owned();
let new_broker_name = addr_str + ":" + port_str;
obj.insert("broker_name".to_owned(), jvalue!(new_broker_name));
}
None => todo!(),
}
})
}
Err(_) => todo!(),
};
}
}
let retval = self.update_class(class_name, function_name, cp);
log::info!("retval: {retval:?}");
return retval;
}
pub fn on_value_request(&self, val: Value, opt_requesting_host_addr: Option<SocketAddr>) -> JuizResult<CapsulePtr> {
let mut cp: CapsuleMap = val.try_into()?;
let class_name = cp.get_param("class_name").unwrap().clone();
let method_name = cp.get_param("method_name").unwrap().clone();
let function_name = cp.get_param("function_name").unwrap().clone();
if let Some(requesting_host_addr) = opt_requesting_host_addr {
cp.set_param("requesting_host_addr", requesting_host_addr.to_string().as_str());
}
match method_name.as_str() {
"create" => self.create_class(class_name.as_str(), function_name.as_str(), cp),
"delete" => self.delete_class(class_name.as_str(), function_name.as_str(), cp),
"read" => self.read_class(class_name.as_str(), function_name.as_str(), cp),
"update" => {
self.on_update(class_name.as_str(), function_name.as_str(), cp, opt_requesting_host_addr)
}
_ => {
Err(anyhow!(JuizError::InvalidValueError{message: format!("qmp_broker received invalid value. Its method name is unknown ({})", method_name)}))
}
}
}
pub fn create_class(&self, class_name: &str, function_name: &str, args: CapsuleMap) -> JuizResult<CapsulePtr> {
self.call_callback(&self.create_callback_container, class_name, function_name, args)
}
pub fn read_class_value2cap(&self, class_name: &str, function_name: &str, args: Value) -> JuizResult<CapsulePtr> {
self.call_callback(&self.read_callback_container, class_name, function_name, args.try_into()?)
}
pub fn update_class_value2cap(&self, class_name: &str, function_name: &str, args: Value) -> JuizResult<CapsulePtr> {
self.call_callback(&self.update_callback_container, class_name, function_name, args.try_into()?)
}
pub fn delete_class_value2cap(&self, class_name: &str, function_name: &str, args: Value) -> JuizResult<CapsulePtr> {
self.call_callback(&self.delete_callback_container, class_name, function_name, args.try_into()?)
}
pub fn read_class(&self, class_name: &str, function_name: &str, args: CapsuleMap) -> JuizResult<CapsulePtr> {
self.call_callback(&self.read_callback_container, class_name, function_name, args)
}
pub fn update_class(&self, class_name: &str, function_name: &str, args: CapsuleMap) -> JuizResult<CapsulePtr> {
self.call_callback(&self.update_callback_container, class_name, function_name, args)
}
pub fn delete_class(&self, class_name: &str, function_name: &str, args: CapsuleMap) -> JuizResult<CapsulePtr> {
self.call_callback(&self.delete_callback_container, class_name, function_name, args)
}
fn call_callback(&self, cb_container: &ClassCallbackContainerType, class_name: &str, function_name:&str, args: CapsuleMap) -> JuizResult<CapsulePtr> {
cb_container.get(class_name).and_then(|cbs| {
cbs.get(function_name)
}).and_then(|cb|{
Some(cb(self.core_broker.clone(), args).and_then(|mut capsule|{
capsule.set_function_name(function_name)?;
capsule.set_class_name(class_name)?;
Ok(capsule)
}))
}).or_else(||{
Some(Err(anyhow!(JuizError::CRUDBrokerCanNotFindFunctionError { class_name: class_name.to_owned(), function_name: function_name.to_owned()})))
}).unwrap()
}
}