use serialize::json::{Object};
use valico::Builder as ValicoBuilder;
use backend::{Request, Response};
use errors::{NotMatchError, ValidationError, Error};
use backend::{HandleResult};
use framework::path::{Path};
use framework::nesting::Nesting;
use framework::{
ApiHandler, ValicoBuildHandler,
Callbacks, ApiHandlers, CallInfo
};
pub struct Namespace {
handlers: ApiHandlers,
path: Path,
coercer: Option<ValicoBuilder>,
before: Callbacks,
before_validation: Callbacks,
after_validation: Callbacks,
after: Callbacks
}
impl Nesting for Namespace {
fn get_handlers<'a>(&'a self) -> &'a ApiHandlers { &self.handlers }
fn get_handlers_mut<'a>(&'a mut self) -> &'a mut ApiHandlers { &mut self.handlers }
fn get_before<'a>(&'a self) -> &'a Callbacks { &self.before }
fn get_before_mut<'a>(&'a mut self) -> &'a mut Callbacks { &mut self.before }
fn get_before_validation<'a>(&'a self) -> &'a Callbacks { &self.before_validation }
fn get_before_validation_mut<'a>(&'a mut self) -> &'a mut Callbacks { &mut self.before_validation }
fn get_after_validation<'a>(&'a self) -> &'a Callbacks { &self.after_validation }
fn get_after_validation_mut<'a>(&'a mut self) -> &'a mut Callbacks { &mut self.after_validation }
fn get_after<'a>(&'a self) -> &'a Callbacks { &self.after }
fn get_after_mut<'a>(&'a mut self) -> &'a mut Callbacks { &mut self.after }
}
impl Namespace {
pub fn new(path: &str) -> Namespace {
Namespace {
handlers: vec![],
path: Path::parse(path, false).unwrap(),
coercer: None,
before: vec![],
before_validation: vec![],
after_validation: vec![],
after: vec![]
}
}
pub fn params(&mut self, builder: ValicoBuildHandler) {
self.coercer = Some(ValicoBuilder::build(builder));
}
pub fn build(path: &str, builder: |&mut Namespace|) -> Namespace {
let mut namespace = Namespace::new(path);
builder(&mut namespace);
return namespace;
}
fn validate(&self, params: &mut Object) -> HandleResult<()> {
if self.coercer.is_some() {
let coercer = self.coercer.as_ref().unwrap();
match coercer.process(params) {
Ok(()) => Ok(()),
Err(err) => return Err(box ValidationError{ reason: err } as Box<Error>)
}
} else {
Ok(())
}
}
}
impl ApiHandler for Namespace {
fn api_call(&self, rest_path: &str, params: &mut Object, req: &mut Request, info: &mut CallInfo) -> HandleResult<Response> {
let rest_path: &str = match self.path.is_match(rest_path) {
Some(captures) => {
let captured_length = captures.at(0).len();
self.path.apply_captures(params, captures);
rest_path.slice_from(captured_length)
},
None => return Err(box NotMatchError as Box<Error>)
};
try!(self.validate(params));
self.push_callbacks(info);
self.call_handlers(rest_path, params, req, info)
}
}