/**
  * Creates an ActionDefinition from a class method
  * 
  * @param ReflectionMethod $method
  * @param Annotation $annotation
  * @param array $additionalAnnotations
  * @return ActionDefinition
  */
 protected function buildAction(ReflectionMethod $method, $annotation = null, array $additionalAnnotations = array())
 {
     $action = new ActionDefinition();
     $action->setName($method->getName());
     if ($annotation) {
         // the annotation is not mandatory but is useful to set some action properties
         $action->setTitle($annotation->title ?: $method->getName())->setIcon($annotation->icon)->setDefault($annotation->default)->setLoadModel($annotation->load_model);
         if ($annotation->menu !== null) {
             $action->setMenu($annotation->menu);
         }
         if ($annotation->pipe) {
             $action->setFlow(ActionDefinition::FLOW_PIPE, $annotation->pipe);
         }
         if ($annotation->redirect) {
             $action->setFlow(ActionDefinition::FLOW_REDIRECT, $annotation->redirect);
         }
         if ($annotation->redirect_with_id) {
             $action->setFlow(ActionDefinition::FLOW_REDIRECT_WITH_ID, $annotation->redirect_with_id);
         }
         if ($annotation->redirect_with_data) {
             $action->setFlow(ActionDefinition::FLOW_REDIRECT_WITH_DATA, $annotation->redirect_with_data);
         }
         if ($annotation->delegate) {
             $action->setFlow(ActionDefinition::FLOW_DELEGATE, $annotation->delegate);
         }
         if ($annotation->on_model) {
             $action->applyToModel($annotation->on_model);
         }
         if ($annotation->confirm) {
             $action->addBehavior(new ConfirmBehavior(array('message' => $annotation->confirm)));
         }
     }
     // some annotations use arguments which could trigger the creation
     // of an input model if their not ignore
     $minNbOfParams = 0;
     $excludeParams = array();
     // additional information provided by other annotations
     $yamlParser = $this->serviceContainer->get('yamlParser');
     foreach ($additionalAnnotations as $anno) {
         if ($anno instanceof \Nucleus\IService\Security\Secure) {
             $perms = $yamlParser->parse($anno->permissions);
             $action->setPermissions($perms);
         } else {
             if ($anno instanceof \Nucleus\IService\Dashboard\Paginate) {
                 $action->addBehavior(new PaginatedBehavior((array) $anno));
                 if ($anno->offset_param !== null) {
                     $minNbOfParams++;
                     $excludeParams[] = $anno->offset_param;
                 }
             } else {
                 if ($anno instanceof \Nucleus\IService\Dashboard\Orderable) {
                     $action->addBehavior(new OrderableBehavior((array) $anno));
                     $minNbOfParams++;
                     $excludeParams[] = $anno->param;
                     if ($anno->order_param !== null) {
                         $minNbOfParams++;
                         $excludeParams[] = $anno->order_param;
                     }
                 } else {
                     if ($anno instanceof \Nucleus\IService\Dashboard\Filterable) {
                         $action->addBehavior(new FilterableBehavior((array) $anno));
                         $minNbOfParams++;
                         $excludeParams[] = $anno->param;
                     } else {
                         if ($anno instanceof \Nucleus\IService\Dashboard\ActionBehavior) {
                             $classname = $anno->class;
                             $params = $yamlParser->parse($anno->params) ?: array();
                             $action->addBehavior(new $classname($params));
                         }
                     }
                 }
             }
         }
     }
     // input
     if (!$annotation || $annotation->in === null) {
         if ($method->getNumberOfParameters() > $minNbOfParams) {
             $action->setInputType(ActionDefinition::INPUT_FORM);
         }
     } else {
         $action->setInputType($annotation->in);
     }
     if ($action->getInputType() === ActionDefinition::INPUT_FORM || $method->getNumberOfParameters() > $minNbOfParams && $action->getInputType() != ActionDefinition::INPUT_DYNAMIC) {
         // builds the input model from the method's arguments
         $inputModel = $this->buildModelFromMethod($method, $additionalAnnotations, $excludeParams);
         if ($method->getNumberOfParameters() == $minNbOfParams + 1) {
             $fields = $inputModel->getFields();
             if (count($fields) === 1 && $fields[0]->hasRelatedModel()) {
                 $action->setModelOnlyArgument($fields[0]->getName());
                 $inputModel = $fields[0]->getRelatedModel();
             }
         }
         $action->setInputModel($inputModel);
     }
     // tries to determine the return type
     if (!preg_match('/@return ([a-zA-Z\\\\]+)(\\[\\])?/', $method->getDocComment(), $returnTag)) {
         $returnTag = false;
     }
     if (!$annotation || !$action->isFlowing() && $annotation->out === null) {
         if ($returnTag) {
             $isArray = isset($returnTag[2]);
             $action->setReturnType($isArray ? ActionDefinition::RETURN_LIST : ActionDefinition::RETURN_OBJECT);
         }
     } else {
         if (!$action->isFlowing()) {
             $action->setReturnType($annotation->out);
         }
     }
     $modelTypes = array(ActionDefinition::RETURN_LIST, ActionDefinition::RETURN_OBJECT, ActionDefinition::RETURN_FORM);
     if (in_array($action->getReturnType(), $modelTypes) && (!$returnTag || $returnTag[1] !== 'array')) {
         if ((!$annotation || $annotation->model === null) && !$returnTag) {
             throw new DefinitionBuilderException("Action '{$action->getName()}' returns something but has no model attached");
         }
         $action->setReturnModel($this->buildModel($annotation && $annotation->model ? $annotation->model : $returnTag[1]));
     }
     return $action;
 }