use indexmap::IndexMap;
use serde_yaml::Value;
use crate::models::*;
use super::statement_lexer::StatementLexer;
pub struct ControllerLexer;
impl ControllerLexer {
pub fn analyze(controllers: &IndexMap<String, Value>) -> IndexMap<String, Controller> {
let mut result = IndexMap::new();
for (name, config) in controllers {
let mut controller = Controller::new(name);
if let Value::Mapping(mapping) = config {
for (key, value) in mapping {
let key_str = key.as_str().unwrap_or("");
match key_str {
"resource" => {
controller.resource = value.as_str().map(|s| s.to_string());
}
"invokable" => {
controller.invokable = value.as_bool().unwrap_or(false);
}
"meta" | "config" => {
if let Value::Mapping(meta) = value {
Self::parse_meta(&mut controller, meta);
}
}
_ => {
if let Value::Sequence(seq) = value {
let statements: Vec<String> = seq
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect();
let parsed = StatementLexer::parse(&statements);
controller.methods.insert(key_str.to_string(), parsed);
} else if let Value::String(s) = value {
let statements = vec![s.to_string()];
let parsed = StatementLexer::parse(&statements);
controller.methods.insert(key_str.to_string(), parsed);
}
}
}
}
}
if controller.methods.is_empty() && controller.is_resource() {
Self::populate_resource_methods(&mut controller);
}
result.insert(name.to_string(), controller);
}
result
}
fn populate_resource_methods(controller: &mut Controller) {
let is_api = controller.is_api_resource();
let resource_actions: Vec<(&str, Vec<&str>)> = if is_api {
vec![
("index", vec!["query:all"]),
("store", vec!["validate", "save"]),
("show", vec!["find"]),
("update", vec!["validate", "update"]),
("destroy", vec!["delete"]),
]
} else {
vec![
("index", vec!["query:all"]),
("create", vec![]),
("store", vec!["validate", "save"]),
("show", vec!["find"]),
("edit", vec!["find"]),
("update", vec!["validate", "update"]),
("destroy", vec!["delete"]),
]
};
for (name, stmts) in resource_actions {
let parsed = StatementLexer::parse(
&stmts.iter().map(|s| s.to_string()).collect::<Vec<_>>()
);
controller.methods.insert(name.to_string(), parsed);
}
}
fn parse_meta(controller: &mut Controller, meta: &serde_yaml::Mapping) {
for (key, value) in meta {
let key_str = key.as_str().unwrap_or("");
match key_str {
"policies" | "policy" => {
controller.policies = value.as_bool().unwrap_or(false);
}
"parent" => {
controller.parent = value.as_str().map(|s| s.to_string());
}
"extends" => {
controller.extends = value.as_str().map(|s| s.to_string());
}
"traits" => {
controller.traits = value.as_str()
.map(|s| s.split(',').map(|t| t.trim().to_string()).collect())
.unwrap_or_default();
}
"implements" => {
controller.implements = value.as_str()
.map(|s| s.split(',').map(|t| t.trim().to_string()).collect())
.unwrap_or_default();
}
"namespace" => {
controller.namespace = value.as_str().map(|s| s.to_string());
}
_ => {}
}
}
}
}