/**
  * Will register a complete aspect to the AspectRegister.
  * This include its advices and pointcuts which can be looked up from this point on
  *
  * @param \AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition $aspectDefinition Structure to register as an aspect
  *
  * @return null
  */
 public function register(AspectDefinition $aspectDefinition)
 {
     // create the new aspect and fill it with things we already know
     $aspect = new Aspect();
     $aspect->setName($aspectDefinition->getName());
     $aspect->setNamespace($aspectDefinition->getNamespace());
     // prepare the tokenizer we will need for further processing
     $needles = array(AfterReturning::ANNOTATION, AfterThrowing::ANNOTATION, After::ANNOTATION, Around::ANNOTATION, Before::ANNOTATION);
     $tokenizer = new Tokenizer();
     $tokenizer->ignore(array('param', 'return', 'throws'));
     // iterate the functions and filter out the ones used as advices
     $scheduledAdviceDefinitions = array();
     foreach ($aspectDefinition->getFunctionDefinitions() as $functionDefinition) {
         $foundNeedle = false;
         foreach ($needles as $needle) {
             // create the advice
             if (strpos($functionDefinition->getDocBlock(), '@' . $needle) !== false) {
                 $foundNeedle = true;
                 $scheduledAdviceDefinitions[$needle][] = $functionDefinition;
                 break;
             }
         }
         // create the pointcut
         if (!$foundNeedle && strpos($functionDefinition->getDocBlock(), '@' . Pointcut::ANNOTATION) !== false) {
             $pointcut = new PointcutDefinition();
             $pointcut->setName($functionDefinition->getName());
             $tokens = new Tokens($tokenizer->parse($functionDefinition->getDocBlock()));
             // convert to array and run it through our advice factory
             $toArray = new ToArray();
             $annotations = $toArray->convert($tokens);
             // create the entities for the join-points and advices the pointcut describes
             $pointcut->setPointcutExpression(new PointcutExpression(array_pop(array_pop($annotations)->values)));
             $aspect->getPointcuts()->add($pointcut);
         }
     }
     $this->add($aspect);
     // do the pointcut lookups where we will need the pointcut factory for later use
     $pointcutFactory = new PointcutFactory();
     foreach ($scheduledAdviceDefinitions as $codeHook => $hookedAdviceDefinitions) {
         foreach ($hookedAdviceDefinitions as $scheduledAdviceDefinition) {
             // create our advice
             $advice = new Advice();
             $advice->setAspectName($aspectDefinition->getQualifiedName());
             $advice->setName($scheduledAdviceDefinition->getName());
             $advice->setCodeHook((string) $codeHook);
             $tokens = new Tokens($tokenizer->parse($scheduledAdviceDefinition->getDocBlock()));
             // convert to array and run it through our advice factory
             $toArray = new ToArray();
             $annotations = $toArray->convert($tokens);
             // create the entities for the join-points and advices the pointcut describes
             foreach ($annotations as $annotation) {
                 $pointcut = $pointcutFactory->getInstance(array_pop($annotation->values));
                 if ($pointcut instanceof PointcutPointcut) {
                     // get the referenced pointcuts for the split parts of the expression
                     $expressionParts = explode(PointcutPointcut::EXPRESSION_CONNECTOR, $pointcut->getExpression());
                     // lookup all the referenced pointcuts
                     $referencedPointcuts = array();
                     foreach ($expressionParts as $expressionPart) {
                         $referencedPointcuts = array_merge($referencedPointcuts, $this->lookupPointcuts($expressionPart));
                     }
                     $pointcut->setReferencedPointcuts($referencedPointcuts);
                 }
                 $advice->getPointcuts()->add($pointcut);
             }
             $aspect->getAdvices()->add($advice);
         }
     }
     $this->set($aspectDefinition->getQualifiedName(), $aspect);
 }