use serde::{Deserialize, Deserializer, Serialize, de};
use serde_json::Value;
use tracing::info;
#[derive(Deserialize, Serialize)]
pub struct Meta {
pub href: String,
}
#[derive(Serialize)]
pub struct Resource {
pub name: String,
pub mimetype: String,
#[serde(rename = "type")]
pub resource_type: String,
pub href: String,
pub content: Option<Content>,
}
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Form {
pub id: u64,
pub name: String,
pub version: String,
pub created: String,
pub created_by: String,
pub updated: String,
pub updated_by: String,
pub status: String,
#[serde(rename = "type")]
pub form_type: String,
pub template_id: String,
pub template_ids: Vec<String>,
pub resources: Vec<Resource>,
}
#[derive(Deserialize, Serialize)]
pub struct FormResponse {
pub meta: Meta,
pub form: Form,
}
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Content {
pub form_id: String,
pub name: String,
pub rm_type: String,
pub language: String,
pub template_languages: Vec<String>,
pub view_config: ViewConfig,
pub children: Vec<ChildElement>,
}
#[derive(Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ChildElement {
pub name: Option<String>,
pub localized_name: Option<String>,
pub rm_type: String,
pub node_id: String,
pub min: i32,
pub max: i32,
pub aql_path: String,
pub fid: Option<String>,
pub form_id: String,
pub view_config: Option<ViewConfig>,
pub children: Option<Vec<ChildElement>>,
}
#[derive(Deserialize, Serialize, Clone)]
pub struct ViewConfig {
pub advanced: Option<AdvancedConfig>,
pub multiplicity: Option<MultiplicityConfig>,
pub field: Option<Value>,
}
#[derive(Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AdvancedConfig {
pub hidden: bool,
pub readonly: bool,
pub hide_frame: Option<bool>,
}
#[derive(Deserialize, Serialize, Clone)]
pub struct MultiplicityConfig {
pub min: i32,
pub max: i32,
}
impl<'de> Deserialize<'de> for Resource {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Intermediate {
name: String,
mimetype: String,
#[serde(rename = "type")]
resource_type: String,
href: String,
content: Option<Value>,
}
let intermediate = Intermediate::deserialize(deserializer)?;
info!("Parsing content for resource {}", intermediate.name);
let content = if intermediate.name == "edit-form-description" {
if let Some(content_value) = intermediate.content {
Some(serde_json::from_value(content_value).map_err(de::Error::custom)?)
} else {
None
}
} else {
None
};
Ok(Resource {
name: intermediate.name,
mimetype: intermediate.mimetype,
resource_type: intermediate.resource_type,
href: intermediate.href,
content,
})
}
}