/**
  * Builds a base validator conjunction for the given data type.
  *
  * The base validation rules are those which were declared directly in a class (typically
  * a model) through some @validate annotations on properties.
  *
  * Additionally, if a custom validator was defined for the class in question, it will be added
  * to the end of the conjunction. A custom validator is found if it follows the naming convention
  * "Replace '\Model\' by '\Validator\' and append "Validator".
  *
  * Example: $dataType is F3\Foo\Domain\Model\Quux, then the Validator will be found if it has the
  * name F3\Foo\Domain\Validator\QuuxValidator
  *
  * @param string $dataType The data type to build the validation conjunction for. Needs to be the fully qualified object name.
  * @return F3\FLOW3\Validation\Validator\ConjunctionValidator The validator conjunction or NULL
  * @author Robert Lemke <*****@*****.**>
  * @author Sebastian Kurfürst <*****@*****.**>
  */
 protected function buildBaseValidatorConjunction($dataType)
 {
     $validatorConjunction = $this->objectManager->getObject('F3\\FLOW3\\Validation\\Validator\\ConjunctionValidator');
     // Model based validator
     if (class_exists($dataType)) {
         $validatorCount = 0;
         $objectValidator = $this->createValidator('F3\\FLOW3\\Validation\\Validator\\GenericObjectValidator');
         foreach ($this->reflectionService->getClassPropertyNames($dataType) as $classPropertyName) {
             $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($dataType, $classPropertyName);
             if (!isset($classPropertyTagsValues['validate'])) {
                 continue;
             }
             foreach ($classPropertyTagsValues['validate'] as $validateValue) {
                 $parsedAnnotation = $this->parseValidatorAnnotation($validateValue);
                 foreach ($parsedAnnotation['validators'] as $validatorConfiguration) {
                     $newValidator = $this->createValidator($validatorConfiguration['validatorName'], $validatorConfiguration['validatorOptions']);
                     if ($newValidator === NULL) {
                         throw new \F3\FLOW3\Validation\Exception\NoSuchValidatorException('Invalid validate annotation in ' . $dataType . '::' . $classPropertyName . ': Could not resolve class name for  validator "' . $validatorConfiguration['validatorName'] . '".', 1241098027);
                     }
                     $objectValidator->addPropertyValidator($classPropertyName, $newValidator);
                     $validatorCount++;
                 }
             }
         }
         if ($validatorCount > 0) {
             $validatorConjunction->addValidator($objectValidator);
         }
     }
     // Custom validator for the class
     $possibleValidatorClassName = str_replace('\\Model\\', '\\Validator\\', $dataType) . 'Validator';
     $customValidator = $this->createValidator($possibleValidatorClassName);
     if ($customValidator !== NULL) {
         $validatorConjunction->addValidator($customValidator);
     }
     return $validatorConjunction;
 }
 /**
  * Creates and returns an aspect from the annotations found in a class which
  * is tagged as an aspect. The object acting as an advice will already be
  * fetched (and therefore instantiated if neccessary).
  *
  * @param  string $aspectClassName Name of the class which forms the aspect, contains advices etc.
  * @return mixed The aspect container containing one or more advisors or FALSE if no container could be built
  * @author Robert Lemke <*****@*****.**>
  */
 protected function buildAspectContainer($aspectClassName)
 {
     if (!$this->reflectionService->isClassReflected($aspectClassName)) {
         return FALSE;
     }
     if (!$this->reflectionService->isClassTaggedWith($aspectClassName, 'aspect')) {
         return FALSE;
     }
     $aspectContainer = new \F3\FLOW3\AOP\AspectContainer($aspectClassName);
     foreach ($this->reflectionService->getClassMethodNames($aspectClassName) as $methodName) {
         foreach ($this->reflectionService->getMethodTagsValues($aspectClassName, $methodName) as $tagName => $tagValues) {
             foreach ($tagValues as $tagValue) {
                 switch ($tagName) {
                     case 'around':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AroundAdvice', $aspectClassName, $methodName);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName);
                         $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut);
                         $aspectContainer->addAdvisor($advisor);
                         break;
                     case 'before':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\BeforeAdvice', $aspectClassName, $methodName);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName);
                         $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut);
                         $aspectContainer->addAdvisor($advisor);
                         break;
                     case 'afterreturning':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterReturningAdvice', $aspectClassName, $methodName);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName);
                         $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut);
                         $aspectContainer->addAdvisor($advisor);
                         break;
                     case 'afterthrowing':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterThrowingAdvice', $aspectClassName, $methodName);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName);
                         $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut);
                         $aspectContainer->addAdvisor($advisor);
                         break;
                     case 'after':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterAdvice', $aspectClassName, $methodName);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName);
                         $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut);
                         $aspectContainer->addAdvisor($advisor);
                         break;
                     case 'pointcut':
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName, $methodName);
                         $aspectContainer->addPointcut($pointcut);
                         break;
                 }
             }
         }
     }
     foreach ($this->reflectionService->getClassPropertyNames($aspectClassName) as $propertyName) {
         foreach ($this->reflectionService->getPropertyTagsValues($aspectClassName, $propertyName) as $tagName => $tagValues) {
             foreach ($tagValues as $tagValue) {
                 switch ($tagName) {
                     case 'introduce':
                         $splittedTagValue = explode(',', $tagValue);
                         if (!is_array($splittedTagValue) || count($splittedTagValue) != 2) {
                             throw new \F3\FLOW3\AOP\Exception('The introduction in class "' . $aspectClassName . '" does not contain the two required parameters.', 1172694761);
                         }
                         $pointcutExpression = trim($splittedTagValue[1]);
                         $pointcutFilterComposite = $this->pointcutExpressionParser->parse($pointcutExpression);
                         $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $pointcutExpression, $pointcutFilterComposite, $aspectClassName);
                         $interfaceName = trim($splittedTagValue[0]);
                         $introduction = $this->objectFactory->create('F3\\FLOW3\\AOP\\Introduction', $aspectClassName, $interfaceName, $pointcut);
                         $aspectContainer->addIntroduction($introduction);
                         break;
                 }
             }
         }
     }
     if (count($aspectContainer->getAdvisors()) < 1 && count($aspectContainer->getPointcuts()) < 1 && count($aspectContainer->getIntroductions()) < 1) {
         throw new \F3\FLOW3\AOP\Exception('The class "' . $aspectClassName . '" is tagged to be an aspect but doesn\'t contain advices nor pointcut or introduction declarations.', 1169124534);
     }
     return $aspectContainer;
 }